您的位置:首页 > 其它

ZOJ3662-Math Magic解题报告

2012-10-16 19:53 483 查看
状态压缩DP,先对M进行质因子分解,记录其次数,然后对M的所有因子进行统计,分别计算每个因子对应的状态(只有当因子的质因子次数和M相同时这一位才置1),也就是说,如果一个数的每一个质因子次数都没有达到M的质因子次数这个数所表示的状态就是0,然后进行状态DP,其实就是递推,不能算是DP,这个用递推会比记忆化搜索要好,因为记忆化搜索的时候要考虑到底要不要取某一个值,取多少个,用异或没有递推的时候用|实现简单

View Code

#include<iostream>
#include<cstdio>
#include<cstring>
#define SUM 1005
#define STATE 20
#define N 105
#define MOD 1000000007
using namespace std;
int dp
[STATE][SUM];
bool isprime[SUM];
int prime[200],cnt;
int dn,res[4];
int g[STATE][100],num[STATE];
void init()
{
int i,j;
memset(isprime,true,sizeof(isprime));
cnt=0;
for(i=2;i<=1000;i++)
{
if(isprime[i])
{
prime[cnt++]=i;
for(j=i*i;j<=1000;j+=i)
isprime[j]=false;
}
}
}
int main()
{
init();
int n,m,k,i,j,temp,tn,pn;
while(scanf("%d%d%d",&m,&n,&pn)!=EOF)
{
tn=n;
dn=0;
memset(dp,0,sizeof(dp));
for(i=0;i<cnt;i++)
{
if(n%prime[i]==0)
{
temp=n;
while(n%prime[i]==0)
{
n/=prime[i];
}
res[dn]=temp/n;//只需要记录每一个质因子对应的最大因子
dn++;
if(n==1)
break;
}
}
int sta;
memset(num,0,sizeof(num));
for(i=1;i<=tn;i++)
{
if(tn%i==0)
{
sta=0;
for(j=0;j<dn;j++)
{
if(i%res[j]==0)
sta|=(1<<j);
}
g[sta][num[sta]++]=i;
}
}
dp[0][0][0]=1;
for(i=0;i<pn;i++)
for(j=0;j<(1<<dn);j++)
for(k=0;k<m;k++)
{
if(dp[i][j][k])
{
for(int l=0;l<(1<<dn);l++)
for(int t=0;t<num[l];t++)
{
if(i+1<=pn&&k+g[l][t]<=m)
{
dp[i+1][j|l][k+g[l][t]]+=dp[i][j][k];
dp[i+1][j|l][k+g[l][t]]%=MOD;
}
}
}
}
printf("%d\n",dp[pn][(1<<dn)-1][m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: