BZOJ 3944 ——Sum 

题目要求给定一个数$N$,$N \leq 2^{32} - 1$,求

$$ans1 = \sum_{i = 1}^N \phi (i), ans2 = \sum_{i = 1}^N \mu (i) $$

——蛤?这个怎么做?我只知道线性筛。。。

先介绍$O(N)$的算法——线性筛。

由于Euler函数和Mobius函数都是积性函数(即对于$(a, b) = 1$, $f(ab) = f(a)f(b)$),可以利用类似贾志鹏线性筛的方法$O(n)$筛出1到$N$所有数的函数值。

 1 #include<cstdio>
 2 #include<cstring>
 3 typedef long long LL;
 4 const int N = 1000050;
 5 LL phi[N], mobius[N];
 6 int pr[300000];
 7 void calc(int n) {                    //计算[1, n]的phi值及mobius值 
 8   memset(phi, -1, sizeof phi);
 9   memset(mobius, -1, sizeof mobius);
10   int prnum = 0, i, j;
11   phi[1] = mobius[1] = 1;
12   for (i = 2; i < n; ++i) {
13     if (phi[i] < 0) {
14       pr[prnum++] = i;
15       phi[i] = i - 1;
16       mobius[i] = -1;
17     }
18     for (j = 0; j < prnum && (LL)i * pr[j] <= n; ++j) {
19       if (i % pr[j]) {
20         phi[i * pr[j]] = phi[i] * (pr[j] - 1);
21         mobius[i * pr[j]] = -mobius[i];
22       } else {
23         phi[i * pr[j]] = phi[i] * pr[j];
24         mobius[i * pr[j]] = 0;
25         break;
26       }
27     }
28   }
29 }
30 int main() {                          //O(n) - O(1)
31   calc(1000000);
32   for (int i = 2; i <= 1000000; ++i) {
33     phi[i] += phi[i - 1];
34     mobius[i] += mobius[i - 1];
35   }
36   long long ans1 = 0, ans2 = 0;
37   int T, n;
38   scanf("%d", &T);
39   while (T--) {
40     scanf("%d", &n);
41     printf("%lld %lld", phi[n], mobius[n]);
42   }
43   return 0;
44 } 
线性筛

相关文章:

  • 2021-08-17
  • 2022-02-02
  • 2021-06-26
  • 2022-12-23
猜你喜欢
  • 2022-01-23
  • 2021-10-09
  • 2020-10-21
  • 2021-06-19
相关资源
相似解决方案