题目链接:https://www.acwing.com/problem/content/description/222/
给定整数N,求1<=x,y<=N且GCD(x,y)为素数的数对(x,y)有多少对。
GCD(x,y)即求x,y的最大公约数。
输入格式
输入一个整数N
输出格式
输出一个整数,表示满足条件的数对数量。
数据范围
1≤N≤10^7
输入样例:
4
输出样例:
4
题解:
首先,用线性筛可以预处理处素数与欧拉函数。
我们定义 count(x)为: 1<=i,j<=N 有多少对gcd(i,j)=x;
那么原问题就转化成
(要求i是素数)那么问题就转化成了,怎么能快速的求出count(x)
因为 count(x)为:1<=i,j<=N 有多少对gcd(i,j)=x , 那么i和j必须是x的倍数,i和j的范围是x,2x,3x.....
*x那么我们把i和j都约掉一个x,那么约掉后的i和j要求i和j互质,那么问题就转化成:
1<=i,j<=
,有多少对数字两两互质。那么很容易想到欧拉函数,euler(x) 是 1到x有多少对数字和x互质,然后用前缀和就可以预处出来
sum[1]=1, sum[i]=sum[i-1]+2*euler[i]
代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e7+5; int v[maxn],prime[maxn],cnt,phi[maxn]; ll sum[maxn]; void init(){ for(int i=2;i<maxn;i++){ if(!v[i]){ prime[cnt++]=i; v[i]=i; phi[i]=i-1; } for(int j=0;j<cnt;j++){ if(prime[j]>v[i]||prime[j]>maxn/i) break; v[i*prime[j]]=prime[j]; phi[i*prime[j]]=phi[i]*(i%prime[j]?prime[j]-1:prime[j]); } } sum[1]=1; for(int i=2;i<maxn;i++) sum[i]=sum[i-1]+2*phi[i]; } int main(){ init(); int n; cin>>n; ll ans=0; for(int i=2;i<=n;i++){ if(v[i]==i){ ans+=sum[n/i]; } } cout<<ans<<endl; return 0; }
来源:https://blog.csdn.net/weixin_42757232/article/details/99684295