您的位置:首页 > 大数据 > 人工智能

2012 Multi-University Training Contest 5-1007 hdu4345

2012-08-07 19:33 302 查看
题目描述:有N个元素的一个集合经过K次置换能变回原来的集合,求k的个数。

解题思路:k为置换群中各独立置换群长度的最小公倍数,k的个数即N以内的总和小于10的质数的乘积(包括1)

比如N=10时,k可为:1,2,3,2*2,5,2*3,7,2*2*2,3*3,2*5,2*2*3,2*7,3*5,2*2*5,3*7,2*3*5,共16个

解法:DP

状态: dp
[i]表示N中满足最小质因子大于等于质数表中第i个质数的k的个数

比如 dp[10][0]=16(第一个质数是2,k=1也算在dp[10][0]里一会儿可以解释)

状态转移: 如果 prim[i]>N: dp
[i]=1 (可以将k=1看作是dp[10][11],即大于N的那个质数的k个数)

否则: dp
[i] = Sigma(dp[N-prim[i]*j][i+1]) j=0,1,…,N/prim[i];

代码:

#include <iostream>
#include <memory.h>
#include <cstdio>

using namespace std;

int ct,prim[1002],num[1002]={0};
long long dp[1002][1002];

long long dfs(int curr,int p)
{
long long tmp;
if(dp[curr][p]) return dp[curr][p];
if(curr<prim[p]){
dp[curr][p] = 1;
return 1;
}
dp[curr][p] = dfs(curr,p+1);
tmp = prim[p];
while(curr>=tmp)
{
dp[curr][p]+=dfs(curr-tmp,p+1);
tmp*=prim[p];
}
return dp[curr][p];
}

int main()
{
int n;
ct = 0;
for(int i=2;i<=1001;i++)
{
if(num[i]==0)
{
prim[ct++] = i;
for(int j=i+i;j<=1000;j+=i) num[j]=1;
}
}
memset(dp,0,sizeof(dp));
while(scanf("%d",&n)!=EOF)
{
printf("%I64d\n",dfs(n,0));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: