CIA3 Sometimes Naive(莫比乌斯反演+积性函数前缀和)

来源:互联网 发布:linux连接数 编辑:程序博客网 时间:2024/06/15 19:10

题意:求x=1ny=1mφ(gcd(x,y))
根据各种老套路化简得 i=1nn/im/id|iφ(i/d)μ(d)
因此我们只需要处理出f[i]=d|iφ(i/d)μ(d),这个函数的前缀和就可以了。暴力跳倍数更新是过不了所有数据的。我们观察这个函数有什么性质,它是个积性函数!积性函数我们可以通过线性素数筛线性的算出!然后,就可以了。
tips:f数组要开ll哟~

#include <bits/stdc++.h>#define ll long long#define N 10000010using namespace std;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;}int tst,n,m,fai[N],prime[N/10],tot=0,mu[N],mnfac[N];ll f[N];bool notprime[N];void Mobius(){    notprime[1]=1;mu[1]=1;fai[1]=1;f[1]=1;    for(int i=2;i<=1e7;++i){        if(!notprime[i]){            prime[++tot]=i;mu[i]=-1;fai[i]=i-1;            f[i]=fai[i]-1;mnfac[i]=i;        }for(int j=1;prime[j]*i<=1e7;++j){            notprime[prime[j]*i]=1;            if(i%prime[j]==0){                mu[i*prime[j]]=0;fai[i*prime[j]]=fai[i]*prime[j];                mnfac[i*prime[j]]=mnfac[i]*prime[j];                if(mnfac[i*prime[j]]==i*prime[j]){                    f[i*prime[j]]=fai[i*prime[j]]-fai[i];                }else f[i*prime[j]]=f[i/mnfac[i]]*f[mnfac[i*prime[j]]];                break;            }mu[i*prime[j]]=-mu[i];fai[i*prime[j]]=fai[i]*fai[prime[j]];            mnfac[i*prime[j]]=prime[j];f[i*prime[j]]=f[i]*f[prime[j]];        }    }for(int i=1;i<=1e7;++i) f[i]+=f[i-1];}int main(){ //   freopen("a.in","r",stdin);    tst=read();Mobius();    while(tst--){        n=read();m=read();if(n>m) swap(n,m);ll ans=0;int last=0;        for(int i=1;i<=n;i=last+1){            last=min(n/(n/i),m/(m/i));            ans+=(ll)(f[last]-f[i-1])*(n/i)*(m/i);        }                printf("%lld\n",ans);    }    return 0;}
阅读全文
0 0
原创粉丝点击