题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2818
Description
给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.
Input
一个整数N
Output
如题
Sample Input
4
Sample Output
4
HINT
hint
对于样例(2,2),(2,4),(3,3),(4,2)
1<=N<=10^7
题目思路:
假设gcd(x,y) = s;
则s是一个素数,且s*a=x;s*b=y;
则a,b互质,gcd(a,b)=1;
我们枚举素数s,求出所有的y<=n的x的个数,则预处理一个前缀和代表所有小于等于t的欧拉函数值的和sum[t]。
则对于任意一个素数满足条件的个数有sum[n/prime[i]]*2-1(有序对交换,所以乘2,舍去(1,1)特解,减一)。
欧拉函数模板可看:https://blog.csdn.net/baodream/article/details/80542418
代码:
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<map>
using namespace std;
#define FOU(i,x,y) for(int i=x;i<=y;i++)
#define FOD(i,x,y) for(int i=x;i>=y;i--)
#define MEM(aA,val) memset(a,val,sizeof(a))
#define PI acos(-1.0)
const double EXP = 1e-9;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const ll MINF = 0x3f3f3f3f3f3f3f3f;
const double DINF = 0xffffffffffff;
const int N = 1e7+5;
int sum[N];
int phi[N],prime[N];
int tot; //计数,表示prime[N]中有多少质数
void Euler(int n){ 筛出所有小于等于n的欧拉函数值和素数
memset(phi,0,sizeof(phi));
tot=0,phi[1]=1;
for(int i=2;i<=n;i++){
if(!phi[i]){
phi[i] = i-1;
prime[tot++]=i;
}
for(int j=0;j<tot&&1ll*i*prime[j]<=n;j++){
if(i%prime[j]!=0) phi[i*prime[j]] = phi[i] * (prime[j]-1);
else{
phi[i*prime[j]] = phi[i]*prime[j];
break;
}
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
std::ios::sync_with_stdio(false);
int n;
while(cin>>n)
{
Euler(n);
sum[0]=0;
for(int i=1;i<=n;i++)
sum[i] = sum[i-1]+phi[i];
int ans=0;
for(int i=0;i<tot;i++)
ans+=sum[n/prime[i]]*2-1;
cout<<ans<<endl;
}
return 0;
}