BZOJ 2154 (莫比乌斯反演)

参考博客https://blog.csdn.net/qkoqhh/article/details/82180994

OIer的题不好玩呀,不过真是佩服这些大佬们。

注意init初始化的时候,for不能直接开到maxn,按理说不会啊,但确实是T了

#include

using namespace std;

typedef long long ll;

const ll mod=20101009;

const int maxn=1e7+10;

bool vis[maxn];
int prime[maxn];
ll pre[maxn],g[maxn],inv[5];
int n,m;

void init(){
    inv[1]=1,g[1]=1,pre[1]=1;
    int tot=0;
    for(int i=2;i<=n;i++){
        if(!vis[i]){
            prime[tot++]=i;
            g[i]=1-i;
        }
        for(int j=0;jn){
                break;
            }
            vis[i*prime[j]]=1;
            if(i%prime[j]==0){
                g[i*prime[j]]=g[i];
                break;
            }else{
                g[i*prime[j]]=g[i]*(1-prime[j]);
            }
        }
        pre[i]=(pre[i-1]+1ll*g[i]*i%mod+mod)%mod;
    }
    for(int i=2;i<=4;i++){
        inv[i]=(mod-mod/i)*inv[mod%i]%mod;
    }
}

int main(){
    scanf("%d%d",&n,&m);
    ll ans=0;
    if(n>m) swap(n,m);
    init();
    for(int l=1,r;l<=n;l=r+1){
        r=min(n/(n/l),m/(m/l));
        if(r>n) r=n;
        ans+=(pre[r]-pre[l-1]+mod)%mod*inv[4]%mod*(n/l)%mod*(m/l)%mod*(n/l+1)%mod*(m/l+1)%mod;
        ans%=mod;
    }
    printf("%lld\n",ans);
    return 0;
}

 

你可能感兴趣的:(组合数学)