洛谷传送门
BZOJ传送门
题目描述
windy学会了一种游戏。
对于 1 1 1到 N N N这 N N N个数字,都有唯一且不同的 1 1 1到 N N N的数字与之对应。
最开始windy把数字按顺序 1 1 1, 2 2 2, 3 3 3,……, N N N写一排在纸上。
然后再在这一排下面写上它们对应的数字。
然后又在新的一排下面写上它们对应的数字。
如此反复,直到序列再次变为 1 1 1, 2 2 2, 3 3 3,……, N N N。
如: 1 2 3 4 5 6
对应的关系为
1->2 2->3 3->1 4->5 5->4 6->6
windy的操作如下
1 2 3 4 5 6
2 3 1 5 4 6
3 1 2 4 5 6
1 2 3 5 4 6
2 3 1 4 5 6
3 1 2 5 4 6
1 2 3 4 5 6
这时,我们就有若干排 1 1 1到 N N N的排列,上例中有 7 7 7排。
现在windy想知道,对于所有可能的对应关系,有多少种可能的排数。
输入输出格式
输入格式:
一个整数, N N N。
输出格式:
一个整数,可能的排数。
输入输出样例
输入样例#1:
3
输出样例#1:
3
输入样例#2:
10
输出样例#2:
16
说明
30%的数据,满足 1 ≤ N ≤ 10 1 \le N \le 10 1≤N≤10 。
100%的数据,满足 1 ≤ N ≤ 1000 1 \le N \le 1000 1≤N≤1000 。
解题分析
显然, 最后的行数为 l c m ( c i r 1 , c i r 2 , c i r 3 . . . c i r m ) lcm(cir_1,cir_2,cir_3...cir_m) lcm(cir1,cir2,cir3...cirm), 其中 c i r i cir_i ciri是其中一个关系环的大小。
那么我们就可以科学 d p dp dp了。依次枚举 ≤ N \le N ≤N的质数, 枚举其指数幂, d p dp dp转移即可。
复杂度大概在 O ( N 2 ) ∼ O ( N 2 l o g ( N ) ) O(N^2)\sim O(N^2log(N)) O(N2)∼O(N2log(N))之间?
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 1005
#define ll long long
ll dp[170][MX], ans;
int n, pcnt;
int pri[MX];
bool npr[MX];
void getpri()
{
for (R int i = 2; i <= n; ++i)
{
if (!npr[i]) pri[++pcnt] = i;
for (R int j = 1; j <= pcnt; ++j)
{
if (i * pri[j] > n) break;
npr[i * pri[j]] = true;
if (!(i % pri[j])) break;
}
}
}
int main(void)
{
R int i, j, k;
scanf("%d", &n);
dp[0][0] = 1; getpri();
for (i = 1; i <= pcnt; ++i)
{
for (j = 0; j <= n; ++j) dp[i][j] = dp[i - 1][j];
for (j = pri[i]; j <= n; j *= pri[i])
for (k = 0; k <= n - j; ++k) dp[i][k + j] += dp[i - 1][k];
}
for (i = 0; i <= n; ++i) ans += dp[pcnt][i];
printf("%lld", ans);
}