莫比乌斯反演笔记
1:知识
设$ n=\prod\limits_{i=1}^k {p_i}^{c_i}$
1.常见函数表达式:
(1).单位函数: $\epsilon(n) = [n=1] $
(2).常函数: \(I(n) = 1\)
(3).幂函数: $ Id_k(n) = n^k $
(4).欧拉函数: $ \varphi(n) =\sum\limits_{i=1}^n[gcd(i,n) = 1] =n\prod\limits_{i=1}^k(1- \frac 1{p_i}) $
(5).莫比乌斯函数:
\[ \mu(n)= \begin{cases}
1, &{n=1} \\
(-1)^k &\forall i,c_i = 1 \\
0 , &\text{otherwise}
\end{cases} \]
(6).除数函数: $ \sigma_k(n) = \sum\limits_{d|n}d^k $
2.卷积常用公式
注:以下*为卷积
(1).$ \mu *I = \epsilon$
(2).$ \varphi * I = Id $
(3).$ Id_k * I = \sigma_k \Leftrightarrow Id_k = \sigma_k * \mu $
(4).$ (Id_k \cdot \mu) * Id_k = \epsilon $
(5).$ (Id_k \cdot \varphi) * Id_k = Id_{k+1} $
3.常见转换
(1).
\[\begin{aligned}
\sum\limits_{i=1}^n \sum\limits_{j=1}^m[gcd(i,j) = k]
&= \sum\limits_{i=1}^{\lfloor \frac nk \rfloor } \sum\limits_{j=1}^{\lfloor \frac mk \rfloor} [gcd(i,j)=1]\\
&= \sum\limits_{i=1}^{\lfloor \frac nk \rfloor } \sum\limits_{j=1}^{\lfloor \frac mk \rfloor} \sum\limits_{d|gcd(i,j)} \mu(d)\\
&= \sum\limits_{d=1}^{\lfloor \frac nk \rfloor } \mu(d)\sum\limits_{i=1}^{\lfloor \frac nk \rfloor } \sum\limits_{j=1}^{\lfloor \frac mk \rfloor} [d|gcd(i,j)]\\
&= \sum\limits_{d=1}^{\lfloor \frac nk \rfloor } \mu(d) \lfloor \frac n{kd} \rfloor \lfloor \frac m{kd} \rfloor\\
\end{aligned}\]
2:例题
(1).[Sdoi2017]数字表格
求 $ \prod\limits_{i=1}^n \prod\limits_{j=1}^m f(gcd(i,j)) mod 1e9+7 $,f(i)为斐波那契数列第i项
化简过程:
\[\begin{aligned}
\prod\limits_{i=1}^n \prod\limits_{j=1}^m f(gcd(i,j))
&=\prod\limits_{k=1}^n\prod\limits_{i=1}^n \prod\limits_{j=1}^m f(k)*[gcd(i,j)=k]\\
&=\prod\limits_{k=1}^n\prod\limits_{i=1}^{\lfloor \frac nk \rfloor}\prod\limits_{j=1}^{\lfloor \frac mk \rfloor}f(k)*[gcd(i,j)=1]\\
&=\prod\limits_{k=1}^n f(k)^{\sum\limits_{i=1}^{\lfloor \frac nk \rfloor}\sum\limits_{j=1}^{\lfloor \frac mk \rfloor} [gcd(i,j)=1]}\\
\end{aligned}\]
先计算上标
\[\begin{aligned}
\sum\limits_{i=1}^{\lfloor \frac nk \rfloor}\sum\limits_{j=1}^{\lfloor \frac mk \rfloor} [gcd(i,j)=1]
&=\sum\limits_{i=1}^{\lfloor \frac nk \rfloor} \sum\limits_{j=1}^{\lfloor \frac mk \rfloor} \sum\limits_{d|gcd(i,j)}\mu(d)\\
&=\sum\limits_{d=1}^{\lfloor \frac nk \rfloor} \mu(d) \sum\limits_{i=1}^{\lfloor \frac nk \rfloor} \sum\limits_{j=1}^{\lfloor \frac mk \rfloor} [d|gcd(i,j)]\\
&=\sum\limits_{d=1}^{\lfloor \frac nk \rfloor} \mu(d) \lfloor \frac n{kd} \rfloor \lfloor \frac m{kd} \rfloor
\end{aligned}\]
套回之前的式子
\[\begin{aligned}
\prod\limits_{k=1}^n f(k)^{\sum\limits_{i=1}^{\lfloor \frac nk \rfloor}\sum\limits_{j=1}^{\lfloor \frac mk \rfloor} [gcd(i,j)=1]}
&=\prod\limits_{k=1}^n f(k)^{\sum\limits_{d=1}^{\lfloor \frac nk \rfloor} \mu(d) \lfloor \frac n{kd} \rfloor \lfloor \frac m{kd} \rfloor}\\
&=\prod\limits_{T=1}^n ( \prod\limits_{d|T}f(d) ^ {\mu(\lfloor \frac Td \rfloor)}) ^{\lfloor \frac nT \rfloor \lfloor \frac mT \rfloor}
\end{aligned}\]
(2).于神之怒加强版
求 $ {\sum\limits_{i=1}^n} {\sum\limits_{j=1}^m} \gcd(i,j)^k $
化简过程:
\[\begin{aligned}
\sum\limits_{i=1}^n\sum\limits_{j=1}^mgcd(i,j)^k
&=\sum\limits_{d=1}^n\sum\limits_{i=1}^n\sum\limits_{j=1}^md^k \cdot[gcd(i,j)=d]\\
&=\sum\limits_{d=1}^nd^k\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=d]
\end{aligned}\]
先把右半边的东西化简一下
\[\begin{aligned}
\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=d]
&=\sum\limits_{i=1}^{\lfloor \frac nd \rfloor}\sum\limits_{j=1}^{\lfloor \frac md \rfloor}[gcd(i,j)=1]\\
&=\sum\limits_{i=1}^{\lfloor \frac nd \rfloor}\sum\limits_{j=1}^{\lfloor \frac md \rfloor}\sum\limits_{x|gcd(i,j)}\mu(x)\\
&=\sum\limits_{x=1}^{\lfloor \frac nd \rfloor}\mu(x)\sum\limits_{i=1}^{\lfloor \frac nd \rfloor}\sum\limits_{j=1}^{\lfloor \frac md \rfloor}[x|gcd(i,j)]\\
&=\sum\limits_{x=1}^{\lfloor \frac nd \rfloor}\mu(x)\lfloor \frac n{dx} \rfloor\lfloor \frac m{dx} \rfloor
\end{aligned}\]
代回原式
\[\begin{aligned}
\sum\limits_{d=1}^nd^k\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=d]
&=\sum\limits_{d=1}^nd^k\sum\limits_{x=1}^{\lfloor \frac nd \rfloor}\mu(x)\lfloor \frac n{dx} \rfloor\lfloor \frac m{dx} \rfloor\\
&=\sum\limits_{d=1}^n\lfloor \frac n{dx} \rfloor\lfloor \frac m{dx} \rfloor\sum\limits_{x=1}^{\lfloor \frac nd \rfloor}d^k\mu(x)\\
&=\sum\limits_{T=1}^n\lfloor \frac nT \rfloor\lfloor \frac mT \rfloor\sum\limits_{d|T}d^k\mu(\lfloor \frac Td \rfloor)
\end{aligned}\]
(3).DZY Loves Math
对于正整数n,定义\(f(n)\)为n所含质因子的最大幂指数。例如\(f(1960)=f(2^3 \times 5^1 \times 7^2)=3\),\(f(10007) = 1\),\(f(1) = 0\)。给定正整数a,b,求下式的值:
\[\begin{aligned}
\sum\limits_{i=1}^a\sum\limits_{j=1}^bf(gcd(i,j))
\end{aligned}\]
开始化简,首先我们枚举gcd(i,j)的值
\[\begin{aligned}
\sum\limits_{i=1}^a\sum\limits_{j=1}^bf(gcd(i,j))
&=\sum\limits_{k=1}^n\sum\limits_{i=1}^a\sum\limits_{j=1}^bf(k)[gcd(i,j)==k]\\
&=\sum\limits_{k=1}^nf(k)\sum\limits_{i=1}^a\sum\limits_{j=1}^b[gcd(i,j)==k]
\end{aligned}\]
然后就是大家都很熟悉的化简模板
\[\begin{aligned}
\sum\limits_{k=1}^nf(k)\sum\limits_{i=1}^a\sum\limits_{j=1}^b[gcd(i,j)==k]
&=\sum\limits_{k=1}^nf(k)\sum\limits_{i=1}^{\lfloor \frac nk \rfloor}\sum\limits_{j=1}^{\lfloor \frac mk \rfloor}[gcd(i,j)==1]\\
&=\sum\limits_{k=1}^nf(k)\sum\limits_{i=1}^{\lfloor \frac nk \rfloor}\sum\limits_{j=1}^{\lfloor \frac mk \rfloor}\sum\limits_{d|gcd(i,j)}\mu(d)\\
&=\sum\limits_{k=1}^nf(k)\sum\limits_{d=1}^{\lfloor \frac nk \rfloor}\mu(d)\sum\limits_{i=1}^{\lfloor \frac nk \rfloor}\sum\limits_{j=1}^{\lfloor \frac mk \rfloor}[d|gcd(i,j)]\\
&=\sum\limits_{k=1}^nf(k)\sum\limits_{d=1}^{\lfloor \frac nk \rfloor}\mu(d)\lfloor \frac n{kd} \rfloor \lfloor \frac m{kd} \rfloor
\end{aligned}\]
设T=kd
\[\begin{aligned}
\sum\limits_{k=1}^nf(k)\sum\limits_{d=1}^{\lfloor \frac nk \rfloor}\mu(d)\lfloor \frac n{kd} \rfloor \lfloor \frac m{kd} \rfloor
&=\sum\limits_{T=1}^n \lfloor \frac nT \rfloor \lfloor \frac mT \rfloor \sum\limits_{d|T} f(d) \mu(\frac Td)
\end{aligned}\]
设 $ \sum\limits_{d|T} f(d) \mu(\frac Td) $ 为 \(F(T)\)
我们就可以获得最终的式子 \(\sum\limits_{T=1}^n \lfloor \frac nT \rfloor \lfloor \frac mT \rfloor F(T)\)
接下来,就要想方法求 \(F(T)\)
设 \(F(T) = {\prod\limits_{i=1}^k p_i^{x_i}}\),\({d=\prod\limits_{i=1}^k} {p_i^{y_i}}\)
$ \mu(\frac Td) $ 会有3种值, 1 , -1 , 0 , 0对结果无影响,所以考虑如何让 $ \mu(\frac Td)!=0 $
若 $ \mu(\frac Td) =1 $ ,则$ \frac Td =1 $ ,所以 $ x_i=y_i $
若 $ \mu(\frac Td) =-1 $ ,则 $ x_i-y_i<=1 $ 且存在 $ x_i!=y_i $
所以,要使 $ F(T) !=0 $ ,必须满足 $ x_i-y_i<=1 $
设 $ a= \max_{i=1}^{k} x_i$,则 $ f(d) =a 或 a-1$
设D中一共有q个质因子的指数为a
分讨
1.q=k
(1)\(f(d)=a\):
\[\sum_{f(d)=a}\mu(\frac{T}{d})f(d)=a\times\sum_{f(d)=a}\mu(\frac{T}{d})=a\times\sum_{i=1}^k(-1)^{k-i}C_k^i=a\times (-1)^{k+1}
\]
(2)\(f(d)=a-1\):
\[\sum_{f(d)=a-1}f(d)\mu(\frac{T}{d})=(a-1)\times\sum_{f(d)=a-1}\mu(\frac{T}{d})=(a-1)\times(-1)^k
\]
所以,当q=k时
\[F(T)=a\times(-1)^{k+1}+(a-1)\times(-1)^k=(-1)^{k+1}
\]
2.q<k
(1)\(f(d)=a\):
\[\sum_{f(d)=a}f(d)\mu(\frac{T}{d})=a\times\sum_{f(d)=a}\mu(\frac{T}{d})=a\times\sum_{i=1}^q(-1)^{q-i}C_q^i\times\sum_{j=0}^{k-q}(-1)^jC_{k-q}^j=0
\]
(2)\(f(d)=a-1\)
\[\sum_{f(d)=a-1}f(d)\mu(\frac{T}{d})=(a-1)\times\sum_{f(d)=a-1}\mu(\frac{T}{d})=(a-1)\times(-1)^q\times\sum_{j=0}^{k-q}(-1)^jC_{k-q}^j=0
\]
所以,当q<k时
\[F(T)=0
\]
F可以在线性筛的过程中求出,代码如下:
#include<bits/stdc++.h>
#define cc putchar(' ')
#define dd putchar('\n')
using namespace std;
const int N=1e7+10;
int pri[N],tot,vis[N],last[N],c[N],sum[N],T,n,m;
//c[i]代表i的最小素数的出现次数
//last[i]代表i的最小素数的c[i]次方
//sum[i]代表上述F(i)
int in(){
int f=1,k=0;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9')k=(k<<3)+(k<<1)+c-'0',c=getchar();
return k*f;
}
void out(long long x){
if(x<0) putchar('-'),x=-x;
if(x<10) putchar(x+'0');
else out(x/10),putchar(x%10+'0');
}
void init(){
for(int i=2;i<=N-10;i++)
{
if(!vis[i])//若是素数
{
pri[++tot]=i;
last[i]=i;//素数的最小素数就是自己
c[i]=1;//只出现1次
sum[i]=1;//因为是素数,所以满足条件1,此时k=1,(-1)^(k+1)=1
}
for(int j=1;j<=tot&&i*pri[j]<=N-10;j++)
{
int x=pri[j]*i;
vis[x]=1;
if(i%pri[j]==0)//若x已有素数pri[j]
{
last[x]=last[i]*pri[j];//因为只多了个pri[j],所以last[x]*pri[j]就行
c[x]=c[i]+1;//pri[j]出现次数加1
int t=x/last[x];//x去掉所有的pri[j]后剩下的值
if(t==1) sum[x]=1;//若t=1,说明x只有pri[j]一个素数,计算可得为1
else sum[x]=(c[x]==c[t]?-sum[t]:0);
//判断x最小素数的出现次数是否与上t的最小素数出现次数相同,若相同则满足条件1,k+1,相当于
//多乘一个-1,若不同则满足条件2,直接赋为0
//sum[x]相当于递归求值,一直找t,一直往前递归,若一路上c[t]全部相同就乘-1,若有一个不同,
//中间有了0,后面无论怎么乘都是0
break;
}
last[x]=pri[j];//若没有素数pri[j],更新last,因为若有pri[j],就已经在上面跳过了
c[x]=1;
sum[x]=(c[i]==1?-sum[i]:0);//c[x]由c[i]转移,这个也是一个递归的过程,详细可见上文
}
}
for(int i=2;i<=N-10;i++)
sum[i]+=sum[i-1];//处理前缀和
}
long long work(int x,int y){//整除分块模板
if(x>y) swap(x,y);
long long ans=0;
for(int l=1,r;l<=x;l=r+1)
{
r=min(x/(x/l),y/(y/l));
ans+=1ll*(sum[r]-sum[l-1])*(x/l)*(y/l);
}
return ans;
}
signed main(){
T=in();
init();
while(T--)
{
n=in(),m=in();
out(work(n,m)),dd;
}
return 0;
}
///////////////////////////////////////////////////
// ♪♪♪ //
///////////////////////////////////////////////////