题意:给定整数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 }
莫比乌斯反演做法:
第一次写反演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 }