您的位置:首页 > 其它

BZOJ2820 YY的GCD 莫比乌斯反演

2017-12-13 15:08 453 查看
∑isprime(p)∑na=1∑mb=1gcd(a,b)==p

∑isprime(p)∑⌊np⌋a=1∑⌊mp⌋b=1gcd(a,b)==1

∑isprime(p)∑⌊np⌋a=1∑⌊mp⌋b=1∑d|gcd(a,b)μ(d)

∑isprime(p)∑⌊np⌋a=1∑⌊mp⌋b=1∑d|a∧d|bμ(d)

∑isprime(p)∑⌊np⌋d=1μ(d)⌊npd⌋⌊mpd⌋

令k=pd

∑nk=1∑isprime(p)∧p|kμ(kp)⌊nk⌋⌊mk⌋

令F(k)=∑isprime(p)∧p|kμ(kp)

∑nk=1F(k)⌊nk⌋⌊mk⌋

线性筛出μ 然后枚举质数的倍数 复杂度约是O(n)

#include<bits/stdc++.h>
#define inf 1000000000
#define ll long long
using namespace std;
const int N=1e7+5;
const int M=1e6+5;
int T,n,m,cnt;
bool mark
;
int pri[M],mu
;
ll f
;
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void getphi() {
mu[1]=1;
for(int i=2; i<N; i++) {
if(!mark[i])pri[++cnt]=i,mu[i]=-1;
for(int j=1; j<=cnt&&pri[j]*i<N; j++) {
mark[i*pri[j]]=1;
if(i%pri[j]==0) {
mu[i*pri[j]]=0;
break;
} else mu[i*pri[j]]=-mu[i];
}
}
for(int i=1; i<=cnt; i++) {
int p=pri[i];
for(int j=1; j*p<N; j++)f[j*p]+=mu[j];
}
for(int i=1; i<N; i++)f[i]+=f[i-1];
}
int main() {
getphi(),T=read();
while(T--) {
ll ans=0;
n=read(),m=read();
if(n>m)swap(n,m);
for(int i=1,j; i<=n; i=j+1) {
j=min(n/(n/i),m/(m/i));
ans+=(f[j]-f[i-1])*(n/i)*(m/i);
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: