求(sum_{i=1}^nsum_{j=1}^n(gcd(i,j)in prime)),(nleq 10^9)。
解
法一:Mobius反演
[ans=sum_{i=1}^nsum_{j=1}^n(gcd(i,j)in prime)
]
[=sum_{pin prime}sum_{i=1}^nsum_{j=1}^n(gcd(i,j)==p)=
]
设
[f(k)=sum_{i=1}^nsum_{j=1}^n(gcd(i,j)==k)
]
[F(k)=[n/k]^2
]
由Mobius反演定理,我们有
[f(k)=sum_{k|d}[n/d]^2mu(d/k)
]
代入,有
[ans=sum_{pin prime}sum_{p|d}[n/d]^2mu(d/p)=
]
[=sum_{d=1}^n[n/d]^2sum_{p|d}mu(d/p)
]
显然后式可以(O(nlog(n)))维护,而前式可以整除分块,于是问题解决。
参考代码
暂缺
法二:初等数论
(sum)一定要拆开来看,枚举一个质数p,时间复杂度我们是能够接受的,于是对于其中一个枚举项i,能满足条件的必然1-n间与之gcd为p的数的个数,该枚举范围为([n/p]),也就是这个范围内与i互质的数的个数,显然想到欧拉函数,于是对于一个质数p所对答案的贡献为(sum_{i=1}^{[n/p]}2varphi(i)-1),之所以乘以2,原因在于统计的是二元组,减去1是防止gcd(1,1)重复,于是维护出欧拉函数前缀和,直接枚举质数即可。
参考代码:
#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define ll long long
#define SIZE 10000000
using namespace std;
ll phi[SIZE+1];
bool check[SIZE+1];
int prime[1000000],pt;
il void prepare(int);
int main(){
int n,i;scanf("%d",&n);
prepare(n);ll ans(0);
for(i=1;i<=pt;++i)ans+=phi[n/prime[i]]*2-1;
printf("%lld",ans);
return 0;
}
il void prepare(int n){
ri int i,j;phi[1]=1;
for(i=2;i<=n;++i){
if(!check[i])prime[++pt]=i,phi[i]=i-1;
for(j=1;j<=pt&&prime[j]*i<=n;++j){
check[i*prime[j]]|=true;
if(!(i%prime[j])){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*phi[prime[j]];
}
}for(i=1;i<=n;++i)phi[i]+=phi[i-1];
}