^m
路漫漫

题意:给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. N <= 10^7

http://www.lydsy.com/JudgeOnline/problem.php?id=2818

 

欧拉线性筛做法:

枚举每个素数p,对答案的贡献就是 phi[ ⌊ n / p ⌋ ] 的前缀和 * 2 - 1  (-1因为(1, 1)只计算一次)

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int MAXN = 10000010;
 6 int p[MAXN], phi[MAXN], x;
 7 long long s[MAXN];
 8 bool f[MAXN];
 9 int n;
10 
11 void getphi() {
12     f[1] = 1;
13     phi[1] = 1;
14     for (int i = 2; i <= n; ++i) {
15         if (!f[i]) {
16             p[++x] = i;
17             phi[i] = i - 1;
18             for (int j = 2; j * i <= n; ++j) {
19                 f[i * j] = 1;
20                 if (j % i ==  0) phi[i * j] = phi[j] * i;
21                 else phi[i * j] = phi[j] * phi[i];
22             }
23         }
24     }
25 }
26 
27 int main() {
28     x = 0;
29     cin >> n;
30     getphi();
31     s[0] = 0;
32     for (int i = 1; i <= n; ++i) s[i] = s[i - 1] + phi[i];
33     long long ans = 0;
34     for (int i = 1; i <= x; ++i) {
35         ans += s[n / p[i]] * 2 - 1; 
36     }
37     cout << ans << "\n";
38     return 0;
39 }
View Code

 

莫比乌斯反演做法:

第一次写反演emmm意外顺利

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 const int MAXN = 10000010;
 6 int p[MAXN], mob[MAXN], x;
 7 long long s[MAXN];
 8 bool f[MAXN];
 9 int n;
10 
11 void getmob() {
12     f[1] = 1;
13     mob[1] = 1;
14     for (int i = 2; i <= n; ++i) {
15         if (!f[i]) {
16             p[++x] = i;
17             mob[i] = -1;
18             for (int j = 2; j * i <= n; ++j) {
19                 f[i * j] = 1;
20                 if (j % i ==  0) mob[i * j] = 0;
21                 else mob[i * j] = -mob[j];
22             }
23         }
24     }
25 }
26 
27 int main() {
28     x = 0;
29     cin >> n;
30     getmob();
31     s[0] = 0;
32     for (int i = 1; i <= n; ++i) s[i] = s[i - 1] + mob[i];
33     long long ans = 0;
34     for (int d = 1; d <= x && p[d] <= n; ++d) {
35         long long nx = n / p[d];
36         long long j = 0;
37         for (int i = 1; i <= nx; i = j + 1) {
38             j = min(nx, nx / (nx / i));
39             ans += (nx / i) * (nx / i) * (s[j] -s[i - 1]);            
40         }
41     }
42     cout << ans << "\n";
43     return 0;
44 }
View Code

 

posted on 2018-03-13 13:39  ^m  阅读(214)  评论(0编辑  收藏  举报