找回密码
 立即注册
首页 业界区 科技 P3601 签到题

P3601 签到题

焦尔蕾 2025-10-20 18:30:01
  1. // 容易注意到 qiandao(i) = i - phi(i)
  2. // phi 是欧拉函数
  3. // 让我们想起最开始求欧拉函数的做法
  4. // 分解质因数, 然后使用 phi(x) = x * 求积_{p in {x 的所有质因数}} (1 - 1 / p)
  5. // 这样的时间复杂度显然过大
  6. // 我们何妨不反着思考
  7. // 既然找到 l <= x <= r 的所有质因子不行, 不如考虑一个质因子是哪些 l <= x <= r 的质因子
  8. #include <iostream>
  9. #include <vector>
  10. using namespace std;
  11. template <typename T>
  12. using vec = vector<T>;
  13. #define int long long
  14. const int N = 1e6 + 10;
  15. vec<int> primes;
  16. bool not_prime[N];
  17. // 线性筛模板
  18. void get_primes(int n) {
  19. for (int i = 2; i <= n; i ++) {
  20. if (!not_prime[i]) {
  21. primes.push_back(i);
  22. }
  23. for (int j : primes) {
  24. if (i * j > n) break;
  25. not_prime[i * j] = true;
  26. if (i % j == 0) {
  27. break;
  28. }
  29. }
  30. }
  31. }
  32. const int mod = 666623333;
  33. int l, r;
  34. vec<int> _pfactors[N];
  35. // 方便写代码的映射
  36. // pfactors(i) 为 i 的质因子们
  37. #define pfactors(i) _pfactors[(i) - l]
  38. signed main() {
  39. get_primes(N - 5);
  40. cin >> l >> r;
  41. // 我们可以遍历所有质数 p < sqrt r
  42. // 这里直接遍历所有 p < sqrt(r 的最大值) 了, 没差
  43. // 为什么是 p < sqrt(r)?
  44. // 对于一个数 x, 它的质因子中最多只会有一个大于 sqrt x
  45. // 这个质因子可以由 x 除以所有其他质因子得到
  46. // 可以想想分解质因数模板中为什么只用遍历到 sqrt x, 一个道理
  47. for (int p : primes) {
  48. // i 为 p 的 >= l 且 <= r 的倍数, 思想类似埃氏筛
  49. for (int i = ((l - 1) / p + 1) * p; i <= r; i += p) {
  50. pfactors(i).push_back(p);
  51. }
  52. }
  53. int ans = 0;
  54. for (int i = l; i <= r; i ++) {
  55. // 下面一段就是分解质因数, 只不过原本是遍历所有 <= sqrt x
  56. // 这里直接用提前求出来的 pfactors
  57. int phi = i, x = i;
  58. for (int p : pfactors(i)) {
  59. phi = phi / p * (p - 1);
  60. while (x % p == 0) x /= p;
  61. }
  62. // 唯一一个大于 > sqrt(x) 的因子, 和分解质因数模板一样
  63. if (x != 1) phi = phi / x * (x - 1);
  64. ans = (ans + i - phi) % mod;
  65. }
  66. cout << ans;
  67. return 0;
  68. }
复制代码

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册