【模板】欧拉反演和莫比乌斯反演

欧拉反演:

核心公式:

$n=\sum \limits_{d|n}^{}\phi(d)$

证明:

统计$1-n$中有多少个数时按与$n$的$gcd$分类即可。

$n=\sum \limits_{d|n}^{} \sum \limits_{i=1}^{n}[gcd(i,n)==d]$

$=\sum \limits_{d|n}^{} \sum \limits_{i=1}^{\frac{n}{d}}[gcd(i,\frac{n}{d})==1]$

$=\sum \limits_{d|n}^{}\phi(\frac{n}{d})$

由约数的对称性,有$n=\sum \limits_{d|n}^{}\phi(d)$。

使用方法:

将所求值反演后推一波式子,可能会降低枚举量。

例:求$\sum \limits_{i=1}^{n}gcd(i,n)$的值。

将$gcd(i,n)$反演,得到原式$=\sum \limits_{i=1}^{n}{\sum \limits_{d|gcd(i,n)}^{}\phi(d)}$

$=\sum \limits_{i=1}^{n}{\sum \limits_{d|i,d|n}^{}{\phi(d)}}$

$=\sum \limits_{d|n}^{}{\sum \limits_{i=1,d|i}^{n}{\phi(d)}}$

$=\sum \limits_{d|n}^{}\phi(d){\sum \limits_{i=1,d|i}^{n}{1}}$

$=\sum \limits_{d|n}^{}\phi(d)\frac{n}{d}$

于是我们把$O(n)$变成了$O(\sqrt{n})$。

莫比乌斯反演:

核心公式:

若$f(n)=\sum \limits_{d|n}^{}g(d)$,则$g(n)=\sum \limits_{d|n}f(d)\mu(\frac{n}{d})$。

其中$\mu(n)=\begin{cases}1 & n=1 \\ (-1)^k &  n是k个互异素数的积 \\ 0 & 其他情况 \end{cases}$。

关于$mu(n)$:

性质1:显然它是积性函数。

性质2:$\sum \limits_{d|n}^{}\mu(d)=[n=1]$

证明:从$n$个数中选偶数个的方案数=选奇数个的方案数=$2^{n-1}$。

感性理解一下就是前$n-1$个数随便选或不选,最后一个数视情况而定。

核心公式证明:

由约数的对称性得到$g(n)=\sum \limits_{d|n}f(\frac{n}{d})\mu(d)$

$=\sum \limits_{d|n}{\sum \limits_{i|\frac{n}{d}}g(i)\mu(d)}$

$=\sum \limits_{i|n}{\sum \limits_{d|\frac{n}{i}}g(i)\mu(d)}$

$=\sum \limits_{i|n}{g(i) \sum \limits_{d|\frac{n}{i}}\mu(d)}$

当$\frac{n}{i}=1$时后面的$\mu(d)$之和为1,否则为0。

此时$i=n$,于是原式等价于$g(n)=g(n)$,证毕。

使用方法:

同欧拉反演,也可以将类似于$[gcd(i,j)=1]$反演成$\sum \limits_{d|gcd(i,j)}\mu(d)$进行操作。

技巧:

  • 推的时候把$\mu(d)$一直提到最前面,一般会出现一个好康的式子。
  • 遇到看起来最简的式子时可以换一个量(乘积之类的)枚举,然后考虑预处理一些东西。

代码(YY的GCD):

#include<bits/stdc++.h>
#define maxn 10000005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long
#define debug(x) cerr<<#x<<": "<<x<<endl
#define fgx cerr<<"--------------"<<endl
#define dgx cerr<<"=============="<<endl

using namespace std;
int x=10000000,p[maxn],mu[maxn],ish[maxn];
int f[maxn],sum[maxn],cnt;

inline int read(){
    int x=0,f=1; char c=getchar();
    for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
    for(;isdigit(c);c=getchar()) x=x*10+c-'0';
    return x*f;
}

inline void init(){
    mu[1]=1;
    for(int i=2;i<=x;i++){
        if(!ish[i]) p[++cnt]=i,mu[i]=-1;
        for(int j=1;j<=cnt;j++){
            if((int)i*(int)p[j]>x) break;
            ish[i*p[j]]=1;
            if(i%p[j]==0) break;
            mu[i*p[j]]=-mu[i];
        }
    }
    for(int i=1;i<=x;i++)
        for(int j=1;j<=cnt;j++){
            if((int)i*(int)p[j]>x) break;
            f[i*p[j]]+=mu[i];
        }
    for(int i=1;i<=x;i++) sum[i]=sum[i-1]+f[i];
}

int main(){
    init();
    int T=read();
    while(T--){
        int n=read(),m=read(); ll ans=0;
        for(int l=1,r=0;l<=min(n,m);l=r+1){
            r=min(n,min(n/(n/l),m/(m/l)));
            ans+=(ll)(n/l)*(ll)(m/l)*(ll)(sum[r]-sum[l-1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
YY的GCD

猜你喜欢

转载自www.cnblogs.com/YSFAC/p/12044166.html
今日推荐