标签:
题解:
所谓对应关系,其实就是一种置换(想成一种环)。对于n个数,一共有m个置换,每个置换的大小为a1,a2,.....am
转化为求a1+a2+.....am=n的最小公倍数的种类(不同的最小公倍数有多少个)
置换的大小可以为1,转化为a1+a2+.....am<=n的最小公倍数的种类
对于每个ai,可以用k个素数的乘积表示
转化为有p个不同的素数,每个素数的幂的最大值的乘积的不同数,保证全部素数的最大幂和<=n
然后dp来做就行了
参考博客
http://www.cnblogs.com/iwtwiioi/p/4104385.html
代码:
第一种 dp[i][j]表示前i个素数和为j的所有可能,使用滚动数组节省空间
#include<bits/stdc++.h> using namespace std; #define pb push_back #define mp make_pair #define se second #define fs first #define ll long long #define CLR(x) memset(x,0,sizeof x) #define MC(x,y) memcpy(x,y,sizeof(x)) #define SZ(x) ((int)(x).size()) #define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define INF 2097152 typedef pair<int,int> P; const double eps=1e-9; const int maxn=1050; const int mod=1e9+7; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } //----------------------------------------------------------------------------- int p[maxn],vis[maxn],n,cnt; ll dp[2][maxn]; void get_prime() { for(int i=2;i<=n;i++) { if(!vis[i]) p[++cnt]=i; for(int j=1;j<=cnt&&p[j]*i<=n;j++) { vis[p[j]*i]=1; if(!(i%p[j])) break; } } } int main() { n=read();cnt=0; get_prime(); int now=1,last=0; dp[last][0]=1; for(int i=1;i<=cnt;i++) { for(int j=0;j<=n;j++) { dp[now][j]=dp[last][j]; for(int k=p[i];j-k>=0;k*=p[i]) dp[now][j]+=dp[last][j-k]; } //for(int j=0;j<=n;j++) dp[last][j]=0; now^=1; last^=1; } ll ans=0; for(int i=0;i<=n;i++) ans+=dp[last][i]; printf("%lld\n",ans); return 0; }
第二种 dp[i][j]表示前i个素数和不超过j的所有可能情况
#include<bits/stdc++.h> using namespace std; #define pb push_back #define mp make_pair #define se second #define fs first #define ll long long #define CLR(x) memset(x,0,sizeof x) #define MC(x,y) memcpy(x,y,sizeof(x)) #define SZ(x) ((int)(x).size()) #define FOR(it,c) for(__typeof((c).begin()) it=(c).begin();it!=(c).end();it++) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define INF 2097152 typedef pair<int,int> P; const double eps=1e-9; const int maxn=1050; const int mod=1e9+7; ll read() { ll x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } //----------------------------------------------------------------------------- int p[maxn],vis[maxn],n,cnt; ll dp[170][maxn]; void get_prime() { for(int i=2;i<=n;i++) { if(!vis[i]) p[++cnt]=i; for(int j=1;j<=cnt&&p[j]*i<=n;j++) { vis[p[j]*i]=1; if(!(i%p[j])) break; } } } int main() { n=read();cnt=0; get_prime(); for(int i=0;i<=cnt;i++) dp[i][0]=1; for(int j=0;j<=n;j++) dp[0][j]=1; for(int i=1;i<=cnt;i++) { for(int j=0;j<=n;j++) { dp[i][j]=dp[i-1][j]; for(int k=p[i];k<=j;k*=p[i]) dp[i][j]+=dp[i-1][j-k]; } } printf("%lld\n",dp[cnt][n]); return 0; }
标签:
原文地址:http://www.cnblogs.com/byene/p/5759411.html