【BZOJ】2693: jzptab 莫比乌斯反演

【题意】2154: Crash的数字表格 莫比乌斯反演,多组询问,T<=10000。

【算法】数论(莫比乌斯反演)

【题解】由上一题,

$ans=\sum_{g\leq min(n,m)}g\sum_{d\leq min(n/g,m/g)}\mu (d)*d^2*sum(n/gd,m/gd)$

令T=gd

$ans=\sum_{T\leq min(n,m)}sum(n/T,m/T)*T\sum_{d|T}\mu (d)*d$

后面部分由积性函数的乘积和约数和也是积性函数可以线性筛得出。

当i%prime[j]=0时,相对于i多出来的因子必然由重复因子即μ(d)=0,故无视即可。

复杂度O(n+T√n)。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1e7,maxn=1e7+10,MOD=1e8+9;//
int s[maxn],sum[maxn],prime[maxn],tot,n,m;
bool mark[maxn];
int SUM(int x,int y){return 1ll*(1ll*x*(x+1)/2%MOD)*(1ll*y*(y+1)/2%MOD)%MOD;}
int main(){
    s[1]=1;sum[1]=1;
    for(int i=2;i<=N;i++){
        if(!mark[i]){s[prime[++tot]=i]=(1-i+MOD)%MOD;}
        for(int j=1;j<=tot&&i*prime[j]<=N;j++){
            mark[i*prime[j]]=1;
            if(i%prime[j]==0){s[i*prime[j]]=s[i];break;}
            s[i*prime[j]]=1ll*s[i]*s[prime[j]]%MOD;
        }
        sum[i]=(1ll*i*s[i]+sum[i-1])%MOD;
    }
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        int z=min(n,m),pos=0,ans=0;
        for(int i=1;i<=z;i=pos+1){
            pos=min(n/(n/i),m/(m/i));
            ans=(ans+1ll*(sum[pos]-sum[i-1]+MOD)*SUM(n/i,m/i)%MOD)%MOD;
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2018-01-16 08:34  ONION_CYC  阅读(317)  评论(0编辑  收藏  举报