bzoj2820 [bzoj2820]YY的GCD(线性素数筛+莫比乌斯反演)

来源:互联网 发布:python简明教程pdf版 编辑:程序博客网 时间:2024/06/06 00:59

求gcd(i,j)为质数的个数。即
pi=1nj=1mgcd(i,j)==p
首先我们可以像bzoj2301一样把后一部分化简,得到(假定n< m)
pd=1n/pμ(d)n/pdm/pd
设k=pd,则得到
k=1np|kμ(k/p)n/km/k
我们预处理出前半部分的前缀和(利用线性素数筛),后面的就是用floor函数分块的套路算啦!素数是O(n/logn)级别的,更新时是均摊O(logn)的,因此预处理的复杂度是O(n)的。总的复杂度是O(T(n))

#include <bits/stdc++.h>using namespace std;#define ll long long#define N 10000010int T,n,m,mu[N],prime[N],tot=0;ll f[N];bool notprime[N];inline int read(){    int x=0;char ch=getchar();    while(ch<'0'||ch>'9') ch=getchar();    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();    return x;}void Mobius(){    memset(notprime,0,sizeof(notprime));    mu[1]=1;notprime[1]=1;    for(int i=2;i<=N;++i){        if(!notprime[i]){            prime[++tot]=i;mu[i]=-1;        }        for(int j=1;prime[j]*i<=N;++j){            notprime[prime[j]*i]=1;            if(i%prime[j]==0){                mu[prime[j]*i]=0;break;            }            mu[prime[j]*i]=-mu[i];        }    }    for(int j=1;j<=tot;++j)        for(int i=1;prime[j]*i<=N;++i)            f[prime[j]*i]+=mu[i];    for(int i=2;i<=N;++i) f[i]+=f[i-1];}ll ANS(int a,int b){    ll re=0;if(a>b) swap(a,b);    int last;    for(int i=1;i<=a;i=last+1){        last=min(a/(a/i),b/(b/i));        re+=(f[last]-f[i-1])*(a/i)*(b/i);    }    return re;}int main(){//  freopen("a.in","r",stdin);    Mobius();    T=read();    while(T--){        n=read();m=read();        printf("%lld\n",ANS(n,m));    }    return 0;}
阅读全文
0 0