各种反演细节梳理&模板

莫比乌斯反演

\(F(n)=\sum\limits_{d|n}f(d)\Rightarrow f(n)=\sum\limits_{d|n}\mu(\frac n d)F(d)\)
\(F(n)=\sum\limits_{n|d}f(d)\Rightarrow f(n)=\sum\limits_{n|d}\mu(\frac d n)F(d)\)
推带\(\gcd\)的题常用式子:\([\gcd(i,j)==1]=\sum\limits_{d|gcd(i,j)}\mu(d)\)
洛谷P3455 [POI2007]ZAP-Queries
\(f(n)=\sum\limits_{i=1}^a\sum\limits_{j=1}^b[\gcd(i,j)==n]\)
1.老实反演
\(F(n)=\sum\limits_{n|d}f(d)=\lfloor\frac a n\rfloor\lfloor\frac b n\rfloor\)
\(f(n)=\sum\limits_{n|d}\mu(\frac{d}{n})\lfloor\frac{a}{d}\rfloor\lfloor\frac{b}{d}\rfloor=\sum\limits_{d=1}^{\lceil\frac{\min(a,b)}{n}\rceil}\mu(d)\lfloor\frac a{nd}\rfloor\lfloor\frac b{nd}\rfloor\)
2.套式子
\(f(n)=\sum\limits_{i=1}^{\lfloor\frac{a}{n}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{b}{n}\rfloor}[\gcd(i,j)==1]=\sum\limits_{d|gcd(i,j)}\sum\limits_{i=1}^{\lfloor\frac{a}{n}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{b}{n}\rfloor}\mu(d)=\sum\limits_{d=1}^{\lfloor\frac{\min(a,b)}{n}\rfloor}\mu(d)\lfloor\frac a{nd}\rfloor\lfloor\frac b{nd}\rfloor\)
整除分块,时间复杂度\(O(\sqrt n)\)

#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG int
#define G if(++ip==ie)if(fread(ip=buf,1,SZ,stdin))
using namespace std;
const int SZ=1<<19,N=50009;
int u[N],pr[N],p;bool f[N];
char buf[SZ],*ie=buf+SZ,*ip=ie-1;
inline int in(){
    G;while(*ip<'-')G;
    R x=*ip&15;G;
    while(*ip>'-'){x*=10;x+=*ip&15;G;}
    return x;
}
int main(){
    u[1]=f[1]=1;
    for(R i=2;i<N;++i){
        if(!f[i])u[pr[++p]=i]=-1;
        for(R j=1;j<=p&&i*pr[j]<N;++j){
            f[i*pr[j]]=1;
            if(i%pr[j]==0)break;
            u[i*pr[j]]=-u[i];
        }
        u[i]+=u[i-1];
    }
    for(R n=in();n;--n){
        R a=in(),b=in(),d=in(),lim=min(a,b)/d,ans=0;
        for(R l=1,r;l<=lim;l=r+1){
            r=min(a/(a/l),b/(b/l));
            ans+=(u[r]-u[l-1])*(a/(d*l))*(b/(d*l));
        }
        printf("%d\n",ans);
    }
    return 0;
}

洛谷P1829 [国家集训队]Crash的数字表格 / JZPTAB
\[\sum_{i=1}^n\sum_{j=1}^m\frac{ij}{\gcd(i,j)}\\=\sum_{k=1}^n\sum_{i=1}^n\sum_{j=1}^m\frac{ij}{k}[\gcd(i,j)==k]\\=\sum_{k=1}^n\sum_{i=1}^\frac{n}{k}\sum_{j=1}^\frac{m}{k}ijk[\gcd(i,j)==1]\\=\sum_{k=1}^nk\cdot\sum_{i=1}^\frac{n}{k}\sum_{j=1}^\frac{m}{k}\sum_{d|\gcd(i,j)}\mu(d)ij\\=\sum_{k=1}^nk\cdot\sum_{d=1}^\frac{n}{k}\mu(d)\sum_{i=1}^\frac{n}{kd}\sum_{j=1}^\frac{m}{kd}d^2ij\\=\sum_{k=1}^nk\cdot\sum_{d=1}^\frac{n}{k}d^2\mu(d)\frac{\frac{n}{kd}(\frac{n}{kd}+1)}{2}\frac{\frac{m}{kd}(\frac{m}{kd}+1)}{2}\]

#include<bits/stdc++.h>
#define LL long long
#define RG register
#define R RG int
#define YL 20101009
using namespace std;
const int N=1e7+9;
int p,pr[N/10],mu[N],s[N];bitset<N>np;
inline LL Sum(LL x){
    return x*(x+1)%YL*((YL+1)>>1)%YL;
}
LL Calc(R n,R m){
    LL ans=0;
    for(R d=1,r;d<=n;d=r+1){
        r=min(n/(n/d),m/(m/d));
        ans=(ans+(s[r]-s[d-1]+YL)*Sum(n/d)%YL*Sum(m/d))%YL;
    }
    return ans;
}
int main(){
    R n,m;LL ans=0;
    cin>>n>>m;
    if(n>m)swap(n,m);
    s[1]=1;
    for(R i=2;i<=n;++i){
        if(!np[i])pr[++p]=i,mu[i]=-1;
        s[i]=(s[i-1]+(LL)i*i%YL*mu[i]+YL)%YL;
        for(R j=1;j<=p&&i*pr[j]<=n;++j){
            np[i*pr[j]]=1;
            if(i%pr[j]==0)break;
            mu[i*pr[j]]=-mu[i];
        }
    }
    for(R k=1,r;k<=n;k=r+1){
        r=min(n/(n/k),m/(m/k));
        ans=(ans+(Sum(r)-Sum(k-1)+YL)*Calc(n/k,m/k))%YL;
    }
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/flashhu/p/10324146.html