2818: Gcd
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1293 Solved: 597
[ Submit][ Status]
Description
给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.
Input
一个整数N
Output
如题
Sample Input
Sample Output
HINT
hint
对于样例(2,2),(2,4),(3,3),(4,2)
1<=N<=10^7
【题解】虽说是一道基础题,但我今天还就要讲一讲,也是讲给自己听的。
莫比乌斯反演可花了我不少时间,这题我就用这种方法做。
首先有么个公式:
反演得:。
它的另一种表述有:
那么如何把这题和它联系在一起呢?
首先我们就来设 f(d) 表示gcd(x,y)==d的x,y 的对数。
设F(d)表示 d|gcd(x,y),即F(d)=sigma f(d*k){ k*d<=n ,k为整数} 显然还有一个较明显的值为F(d)=(n/d)*(n/d)。
题目让我们求x,y,使gcd(x,y) is prime(素数)。那么我们枚举这个素数p,有
虽然有点快,但慢慢理解吧!这样是要TLE的,所以现在的目标就是如何做一些处理。
首先我们将设 T=pd,则原式为 。
瞧见没,后面的括号就可一来预处理。我们设一个g 函数,,p 为x的一个质因子,g(x)是指和。这里提一下莫比乌斯函数的一些性质,
u(x) //抱歉我用u 来代替。
x=1时 u(x)=1;
x=p1*p2*p3...pr (p,为r个不同的素数)时u(x)=(-1)^r;
否则u(x)=0;
所以对于g(x)我们分类讨论枚举一个质数k,如果
一、当 k|x
{
g(x*k)=u(x) if k==p //如果k==p,则g(x*k)=u(x*k/p)=u(x),即k*x 这个值/p 的函数值;
g(x*k)=0 if k!=p //存在某个质数的平方,所以为0;
}
二、当k不能整出x时
{
g(x*k)=-u(x); if(k==p) //因为是一样的,所以奇偶性不变。
g(x*k)=u(x)-g(x) if(k!=p)//新的质数加入,所以根据莫比乌斯的奇偶性,取反,在加入一个新值
}
最后附上代码。
#include<cstdio>
#include<cstring>
int f[10000001],prime[10000001],g[10000001],sum[10000001],u[10000001],n;
inline void mobius()
{
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
int tot=0;
for(int i=2;i<=n;i++)
{
if(!f[i]){prime[++tot]=i;u[i]=-1;g[i]=1;}
for(int j=1;j<=tot && prime[j]*i<=n;j++)
{
f[i*prime[j]]=prime[j];
if(i%prime[j]){
u[i*prime[j]]=-u[i];
g[i*prime[j]]=u[i]-g[i];
}else{
u[i*prime[j]]=0;
g[i*prime[j]]=u[i];
break;
}
}
}sum[0]=0;
for(int i=1;i<=n;i++)sum[i]=sum[i-1]+g[i];
}
int main()
{
scanf("%d",&n);
mobius();long long ans=0;
for(int i=1,last;i<=n;i=last+1)
{
last=n/(n/i);
ans+=(long long)(n/i)*(n/i)*(sum[last]-sum[i-1]);
}printf("%lld\n",ans);
return 0;
}