莫比乌斯反演

坑先留着,noip之后再补
PoPoQQQ的课件

证明

灭世星痕的博客
peng-ym的博客

例题

[luogu2257]YY的GCD

peng-ym的blog
跟着推了一遍,觉得好妙

#include<bits/stdc++.h>
#define N 10000002
using namespace std;
inline void read(int &x){
    x=0;char c=getchar();int p=1;
    while(!isdigit(c)){if(c=='-')p=-1;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c-48);c=getchar();}
    x*=p;   
}
typedef long long ll;
inline void print(ll x){
    int cnt=0,a[15];
    do{a[++cnt]=x%10,x/=10;}while(x);
    for(int i=cnt;i>=1;i--)putchar(a[i]+'0');
    puts("");
}
bool vis[N];
ll sum[N];
int cnt,prim[N],mu[N],g[N];
inline void get_mu(int n){
    mu[1]=1;
    for(int i=2;i<=n;i++){
        if(!vis[i])mu[i]=-1,prim[++cnt]=i;
        for(int j=1;j<=cnt&&prim[j]*i<=n;j++){
            vis[i*prim[j]]=1;
            if(i%prim[j]==0)break;else mu[prim[j]*i]=-mu[i];
        }
    }
    for(int j=1;j<=cnt;j++)for(int i=1;i*prim[j]<=n;i++)g[i*prim[j]]+=mu[i];
    for(int i=1;i<=n;i++)sum[i]=sum[i-1]+1ll*g[i];
}
int n,m;
int main(){
    int t;read(t);
    get_mu(10000000);
    while(t--){
        read(n);read(m);
        if(n>m)swap(n,m);
        ll ans=0;
        for(int l=1,r;l<=n;l=r+1){
            r=min(n/(n/l),m/(m/l));
            ans+=1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);
        }
        print(ans);
    }
    return 0;
}
posted @ 2018-11-08 10:50  lnyzo  阅读(64)  评论(0编辑  收藏  举报