2818:GCD
Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 6967 Solved: 3085
[submit] [status] [discuss]
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
想说的话
我的数论一直很菜 看了看题解发现是莫比乌斯反演但是我不会
于是乎我就自己想啊想
想到了欧拉函数
题解
我们先用一个函数算出phi函数的值
然后我们思考一下这个题我们就相当于从gcd(a,b)为素数
变成了对于每个范围里面的素数【1,b/a】中有序互质数对的个数
而求1~m中有序互质对x,y的个数,可以令y >= x, 当y = x时,有且只有y = x = 1互质,当y > x时,确定y以后符合条件的个数x就是phiy
所以有序互质对的个数为(1 ~ n/p)的欧拉函数之和乘2减1(要求的是有序互质对,乘2以后减去(1, 1)多算的一次)
那么就只需要先筛出欧拉函数再求个前缀和就可以了
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 10000005
#define ll long long
ll sum[N],phi[N],pri[1000001],n,p,tot,ans;
bool mark[N];
void getphi()
{
phi[1]=1;
for(ll i=2;i<=n;i++)
{
if(!mark[i]){phi[i]=i-1;pri[++tot]=i;}
for(ll j=1;j<=tot;j++)
{
ll x=pri[j];
if(i*x>n)break;
mark[i*x]=1;
if(i%x==0){phi[i*x]=phi[i]*x;break;}
else phi[i*x]=phi[i]*phi[x];
}
}
}
int main()
{
scanf("%lld",&n);
getphi();
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1]+phi[i];
}
for(int i=1;i<=tot;i++)
{
ans+=sum[n/pri
[i]]*2-1;
}
cout<<ans<<endl;
}