windy 学会了一种游戏。对于 到 这 个数字,都有唯一且不同的 到 的数字与之对应。最开始 windy 把数字按顺序 写一排在纸上。然后再在这一排下面写上它们对应的数字。然后又在新的一排下面写上它们对应的数字。如此反复,直到序列再次变为 。
如: 对应的关系为
windy 的操作如下:
这时,我们就有若干排
链接
题解
对于一个置换,我们可以将其分解为若干个循环,问题中的「排数」即为这些循环长度的最小公倍数。设这些循环长度分别为
对于某个
为了便于统计,我们只考虑每个
这种情况下,
现在的问题变成,有一些质数
代码
#include <cstdio>
const int MAXN = 1000;
int primes[MAXN], isNotPrime[MAXN + 1], cnt;
inline void getPrimes() {
isNotPrime[0] = isNotPrime[1] = true;
for (int i = 2; i <= MAXN; i++) {
if (!isNotPrime[i]) {
primes[++cnt] = i;
}
for (int j = 1; j <= cnt && i * primes[j] <= MAXN; j++) {
isNotPrime[i * primes[j]] = true;
if (i % primes[j] == 0) break;
}
}
// for (int i = 0; i < cnt; i++) printf("%d\n", primes[i]);
}
int main() {
int n;
scanf("%d", &n);
getPrimes();
static long long f[MAXN + 1][MAXN + 1];
f[0][0] = 1;
for (int i = 1; i <= cnt; i++) {
for (int k = 0; k <= n; k++) f[i][k] = f[i - 1][k];
for (int p = primes[i]; p <= n; p *= primes[i]) {
for (int k = p; k <= n; k++) {
f[i][k] += f[i - 1][k - p];
}
}
// for (int k = 0; k <= n; k++) printf("f[%d][%d] = %d\n", i, k, f[i][k]);
}
long long ans = 0;
for (int i = 0; i <= n; i++) ans += f[cnt][i];
printf("%lld\n", ans);
return 0;
}