bzoj2820 YY的GCD【莫比乌斯反演】

来源:互联网 发布:清华在线网络教育平台 编辑:程序博客网 时间:2024/06/07 11:02

解题思路:

题目大意即为求:

pPi=1nj=1m[gcd(i,j)=p]

原式=pPi=1npj=1mp[gcd(i,j)=1]

=pPi=1npj=1mpϵ(gcd(i,j))

=pPi=1npj=1mpd|gcd(i,j)μ(d)

=pPi=1npj=1mpd|i,d|jμ(d)

=pPdi=1npdj=1mpdμ(d)

=pPdμ(d)npdmpd

这里我们设T=pd,则d=Tp,现在改为枚举T,则

原式=TnTmTpP,p|Tμ(Tp)

g(x)=pP,p|xμ(xp)

那么关键在于求g(x)的前缀和。

考虑线性筛法。

对于一个质数p0

p0|x,则μ(p0x)=0,那么当pp0,有mu(p0xp)=0,所以此时

g(p0x)=pP,p|p0xμ(p0xp)=μ(x)

p0不整除x,则有

g(p0x)=pP,p|xμ(xp)μ(p0)+μ(p0xp0)

g(p0x)=g(x)+μ(x)

所以可以线性筛出g(x),那么本题就可以O(n)预处理,O(n)查询了。

#include<cstdio>#include<iostream>#include<cstring>#include<string>#include<algorithm>#include<cmath>#include<ctime>#include<vector>#include<set>#include<complex>#define ll long longusing namespace std;int getint(){    int i=0,f=1;char c;    for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());    if(c=='-')f=-1,c=getchar();    for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';    return i*f;}const int N=1e7+5,INF=0x3f3f3f3f;int T,n,m,pn;int pri[N],mu[N],g[N],sum[N];void sieve(){    memset(mu,INF,sizeof(mu));    mu[1]=1;    for(int i=2;i<=1e7;i++)    {        if(mu[i]==INF)pri[++pn]=i,mu[i]=-1,g[i]=1;        for(int j=1;j<=pn;j++)        {            ll k=1ll*i*pri[j];            if(k>1e7)break;            if(i%pri[j]==0)            {                mu[k]=0;                g[k]=mu[i];                break;            }            else            {                mu[k]=-mu[i];                g[k]=mu[i]-g[i];            }        }        sum[i]=sum[i-1]+g[i];    }}int main(){    //freopen("lx.in","r",stdin);    //freopen("lx.out","w",stdout);    sieve();    T=getint();    while(T--)    {        n=getint(),m=getint();        if(n>m)swap(n,m);        ll ans=0;        for(int i=1,j;i<=n;i=j+1)        {            j=min(n/(n/i),m/(m/i));            ans+=1ll*(n/i)*(m/i)*(sum[j]-sum[i-1]);        }        printf("%lld\n",ans);    }    return 0;}
原创粉丝点击