Description
给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.
Input
一个整数N
Output
如题
Sample Input
4
Sample Output
4
HINT
对于样例(2,2),(2,4),(3,3),(4,2)
1<=N<=10^7
Solution
此题是一道好题。我们欲求gcd(a,b)=p(p是质数)的a,b对数,可以枚举p,求gcd(a/p, b/p)=1的a/p,b/p的对数。
这个是i以内互质的数对的数量(有序的),所以跟欧拉函数的前缀和有关。
然后线性筛出欧拉函数表求出前缀和。发现答案
Ans=Σ sum[n/prime[i]]∗2−1
.
至于乘以二是因为有序,每一个都减一是因为每次(1, 1)[*p后]被重复算了一遍。
Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 10000002
using namespace std;
int n, prime[N], cnt, phi[N];
long long Ans, sum[N];
bool vis[N];
void work(){
vis[1] = true;
phi[1] = 1;
for(int i = 1; i <= n; i++){
if(!vis[i]){
prime[++cnt] = i;
phi[i] = i - 1;
}
for(int j = 1; j <= cnt && i * prime[j] <= n; j++){
vis[i * prime[j]] = true;
if(i % prime[j] == 0){
phi[i * prime[j]] = phi[i] * prime[j];
break;
}
else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
}
}
sum[0] = 0;
for(int i = 1; i <= n; i++)
sum[i] = sum[i-1] + (long long)phi[i];
Ans = 0;
for(int i = 1; i <= cnt; i++)
Ans += sum[n / prime[i]] * 2 - 1;
}
int main(){
scanf("%d", &n);
work();
printf("%lld", Ans);
return 0;
}