bzoj1025: [SCOI2009] 游戏 6
DP。
每种排法的长度对应所有循环节长度的最小公倍数。
所以排法总数为和为n的几个数的最小公倍数的总数。
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int maxn = 1000 + 10; int cnt,n; long long f[maxn][maxn]; int prime[maxn]; bool not_prime[maxn]; void get_prime(int n) { for(int i = 2; i <= n; i++) if(!not_prime[i]) { prime[++cnt] = i; for(int j = i*i; j <= n; j += i) not_prime[j] = true; } } int main() { scanf("%d",&n); if(n == 1) printf("1\n"); else { get_prime(n); f[0][0] = 1; for(int i = 1,p; i <= cnt; i++) { p = prime[i]; memcpy(f[i],f[i-1],sizeof(f[i])); for(;p <= n; p*=prime[i]) for(int j = p; j <= n; j++) f[i][j] += f[i-1][j-p]; } long long res = 0; for(int i = 0; i <= n; i++) res += f[cnt][i]; printf("%lld\n",res); } return 0; }