1 条题解
-
0
自动搬运
来自洛谷,原作者为

rouxQ
**搬运于
2025-08-24 22:19:16,当前版本为作者最后更新于2020-04-06 10:28:16,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
首先这题和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
- 5331
- 时间
- 2000ms
- 内存
- 250MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者