1 条题解
-
0
首先这题和P4161几乎一模一样,(P4161要求k的个数,本题求所有k的和),
所以双倍经验然后我们来看这题,可以发现如果循环了几次可以回到原地,当且仅当形成了一个环,假如设每个环的长度是 ,那么可以发现 ,又知道 其实就是将那几个数分解质因数,然后取每个质数的最高次幂乘起来,所以我们可以想到枚举素数来做dp。
我们设 表示前 个素数总和为 的所有 的总和,枚举第 个素数的幂进行转移,因为之前并没有用过第 个素数,所以应把上一个状态乘上 ,所以直接有方程
接着发现这个东西可以滚动数组压缩一下,于是可以省掉一维 ,倒序枚举即可,初始状态 ,最后答案是
代码
#include <bits/stdc++.h> #define ll long long//注意开long long using namespace std; const int N = 1e4 + 3; bool vis[N]; vector<int> p; ll f[N] = {1}, m;int n; int main (){ p.push_back(0);//让素数的下标从一开始,使后面的转移更简洁 cin >> n >> m; for (int i = 2; i <= n; i++){ if (!vis[i])p.push_back(i); for (int j = i * i; j <= n; j += i)vis[j] = 1; }//埃筛筛素数 for (int i = 1; i < p.size(); i++) for (int j = n; j >= p[i]; j--){ int tmp = p[i]; while(tmp <= j) f[j] = (f[j] + f[j - tmp] * tmp % m) % m, tmp *= p[i]; } ll Ans = 0; for (int i = 0; i <= n; i++)Ans = (Ans + f[i]) % m; cout << Ans << endl; return 0; }
- 1
信息
- ID
- 6872
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 36
- 已通过
- 12
- 上传者