【51NOD 1192】Gcd表中的质数

来源:互联网 发布:智能电视遥控器软件 编辑:程序博客网 时间:2024/06/08 11:19

Description


i=1nj=1m(gcd(i,j)?1:0)

数据组数T<=1000
1<=M,N<=5106

Solution

很裸的一道莫比乌斯反演题,
先保证n<=m
fi表示gcd为d的倍数的数的个数
则:

fi=mini

gi表示gcd为i的数的个数,
则:
fd=i=1ndgid

根据反演:
gd=i=1ndfidμ(i)

所以枚举每个的质数作为d即可,然而有T组数据,还过不了,
考虑一下每个f对答案的贡献,
fi对答案的贡献为sumifi
因为d为质数,
所以,设p为i中的质因数,则sumi=μ(ip)
这样做可以过,

优化:
因为mu(i)只有当i为质数的乘积是,它才不为0,
所以只有当组成i的所有质数的指数都为1时sumi0
或者组成i中的所有质数的指数只有一个为2时,sumi=11

因为要用分块,所以把sum做一下前缀和,

复杂度:O(n+nn)

Code

#include <iostream>#include <cstdio>#include <cstdlib>#define fo(i,a,b) for(int i=a;i<=b;i++)using namespace std;typedef long long LL;const int N=5*1e6+10;int read(int &n){    char ch=' ';int q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}LL n,m;bool prz[N];int pr[N/5];LL ans,mu[N];int hm[N],ssg[N];bool ssg1[N];LL sum[N];int main(){    int q,w;    prz[1]=mu[1]=1;    fo(i,2,N-1)    {        if(!prz[i])pr[++pr[0]]=i,mu[i]=-1,hm[i]=ssg[i]=1;        fo(j,1,pr[0])        {            int t=pr[j]*i;            if(t>=N)break;            prz[t]=1;            if(i%pr[j]==0)            {                ssg[t]=ssg[i]+1;                ssg1[t]=ssg1[i];                break;            }            mu[t]=-mu[i];            ssg[t]=ssg[i];ssg1[t]=!ssg1[i];            hm[t]=hm[i]+hm[pr[j]];        }    }    fo(i,2,N-1)sum[i]+=-hm[i]*mu[i]+(ssg1[i]?1:-1)*(ssg[i]==2)+sum[i-1];    for(int _=read(_);_;_--)    {        scanf("%lld%lld",&n,&m);        if(n>m)swap(n,m);        ans=0;        int i=2;        while(i<=n)        {            int q=min(n/(n/i),m/(m/i));            ans+=(m/i)*(n/i)*(sum[q]-sum[i-1]);            i=q+1;        }        printf("%lld\n",ans);    }    return 0;}
0 0
原创粉丝点击