将各个数字与它的对应数字连边,就可以得到若干个环。排数就是这些环的最小公倍数,且节点数为n。
于是题意就是问和为n的若干个数的最小公倍数(LCM)有多少种。
记f[i][j]表示前i个质数的和为j时的LCM方案数。
f[i][j]=f[i-1][j]+ ∑q[i]k≤jk=1f[i−1][j−q[i]k]
#include<cstdio>
#define MAXN 1010
int q[MAXN], cnt=0;
bool p[MAXN];
long long f[MAXN][MAXN];
int main()
{
int n;
scanf("%d",&n);
for(int i = 2; i <= n; i++)
if(!p[i])
{
q[++cnt]=i;
for(int j = i*i; j <= n; j+=i)
p[j]=1;
}
f[0][0]=1;
for(int i = 1; i <= cnt; i++)
{
for(int j = 0; j <= n; j++)
{
f[i][j]=f[i-1][j];
for(int k = q[i]; j>=k; k*=q[i])
{
f[i][j]+=f[i-1][j-k];
}
}
}
long long ans=0;
for(int i =0; i <= n; i++)
ans+=f[cnt][i];
printf("%lld",ans);
return 0;
}