joke3579大佬一直劝说我来切莫反
于是我切了一顿发现我一道都不会
所以写个这么个东西来稍微总结一下
莫比乌斯反演
首先莫比乌斯函数和狄利克雷卷积我就不说是什么东西了
整除分块不会的去看oiwiki抄一份过来就行
直接进入正题
反演公式
若\(f(n)=\sum\limits_{d|n}g(d)\),则有\(g(n)=\sum\limits_{d|n}\mu(d)f(\frac{n}{d})\)
证明自己看课件 不解释 实际上感觉在搞这几道题的时候基本没有在用这个 都是在套路
然后说几个小东西 一律不证明
1.\(\sum\limits_{d|n}\mu(d)=[n=1]\)
2.\(\sum\limits_{d|n}\phi(d)=n\) (有时候会用到)
然后开始吧 首先来一些简单的板子吧
注:以下均假定\(n<=m\)
题面:求
\[\sum_{i=1}^{n}\sum_{j=1}^{m}[\gcd(i,j)=d]
\]
首先我们入门先讨论d=1的情况
当d=1时,我们可以采用我们刚才的小东西来搞他一下
\[\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=1]
\]
\[=\sum_{i=1}^n\sum_{j=1}^m\sum_{d|\gcd(i,j)}\mu(d)
\]
\[=\sum_{i=1}^n\sum_{j=1}^m\sum_{d|i,d|j}\mu(d)
\]
然后是一个常见的套路,把我们要的d提到前面来 在很多这种情况都适用的
\[=\sum_{d=1}^{n}\mu(d)\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor
\]
解释一下后面那两个东西:
首先我们把d提前了,我们就要算每个i,j对d的贡献度。
因为\(d|i,d|j\),所以对于任意\(i\),都有\(i=kd\),k是一个常数。j同理。
然后放下j不管,只看i,每个d总共会被统计\(\lfloor\frac{n}{d}\rfloor\)次。
j按照同样的方式计算,于是就出了这个看起来比较正常的柿子。
而我们知道这个东西可以整除分块\(O(\sqrt n)\)搞出来
所以线性筛出\(\mu\)的前缀和就可以乱搞了
然后是这个题,d是任意数的情况。根据gcd的性质,我们直接把所有东西除一个d,变成如下形式:
\[\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}[\gcd(i,j)=1]
\]
然后就变成上面的板子了。
双倍经验:P2522 Problem B
就是i从a开始,j从b开始,容斥成四个上面的东西搞就行了。
2.一些不一样的东西
题意:求
\[\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)\in prime]
\]
某种程度上这个题和题库的后面所有题都是差不多类的 提供了一种新的优化方法
接下来先按照我们刚才看到的东西来化一下
\[\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)\in prime]
\]
\[=\sum_{k\in prime}\sum_{i=1}^n\sum_{j=1}^m[\gcd(i,j)=k]
\]
\[=\sum_{k\in prime}\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}[\gcd(i,j)=1]
\]
\[=\sum_{k\in prime}\sum_{i=1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{k}\rfloor}\sum_{d|\gcd(i,j)}\mu(d)
\]
\[=\sum_{k\in prime}\sum_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor
\]
于是我们把所有的质数筛出来然后大力分块搞就行了……吗?
(我没敢交)
反正无论如何我们还得优化就是了
这里还有一个常用的东西:我们设\(T=kd\),则原式
\[=\sum_{k\in prime}\sum_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor
\]
把T提前,于是有:
\[=\sum_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{d=1}^{\lfloor\frac{n}{k}\rfloor}\mu(d)(k\in prime)
\]
然后因为\(T=kd\),所以\(d=\frac{T}{k}\),于是原式
\[=\sum_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{d|T}\mu(\frac{T}{d})(d\in prime)
\]
把第二个\(\sum\)后面的东西提出来,我们如果有它的前缀和就可以\(O(\sqrt n)\)搞了。发现这个东西可以和素数一起筛出来。你问我怎么筛?
分析后面这一坨东西的性质,既然只在d是质数的时候有贡献那么直接预处理一顿就行了。具体实现如下:
void getmiu() {
mu[1]=1;
for (int i=2;i<=10000000;i++) {
if (!notprime[i]) prime[++cnt]=i,mu[i]=-1;
for (int j=1;j<=cnt&&i*prime[j]<=10000000;j++) {
notprime[i*prime[j]]=1;
if (i%prime[j]==0) break;
mu[i*prime[j]]=-mu[i];
}
}
for (int i=1;i<=cnt;i++)
for (int j=1;prime[i]*j<=10000000;j++)
f[j*prime[i]]+=mu[j];//这一行直接把所有能造成贡献的数累加
for (int i=1;i<=10000000;i++)
sum[i]=sum[i-1]+f[i];
}
结束。
当然,也有一些题的函数可以线性筛出来。比如下题:
题意:
\[\sum_{i=1}^n \sum_{j=1}^m \gcd(i,j)^k
\]
(jzptab那个题其实差不多但是我不想写lcm因为latex木有\lcm这东西)
看到gcd第一反应开始代换:
\[=\sum_{e=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{m}e^k(\gcd(i,j)=e)
\]
\[=\sum_{e=1}^n\sum_{i=1}^{\lfloor\frac{n}{e}\rfloor}\sum_{j=1}^{\lfloor\frac m e \rfloor}e^k\sum_{d|\gcd(i,j)}\mu(d)
\]
\[=\sum_{e=1}^{n}e^k\sum_{d=1}^{\lfloor\frac n e \rfloor}\mu(d)\lfloor \frac n{ed} \rfloor\lfloor\frac m{ed}\rfloor
\]
然后按照套路,设\(T=ed\)
\[=\sum_{e=1}e^k\sum_{d=1}^{\lfloor\frac ne\rfloor}\mu(d)\lfloor\frac nT\rfloor\lfloor\frac mT\rfloor
\]
\[=\sum_{T=1}^{n}\lfloor\frac nT\rfloor\lfloor\frac mT\rfloor\sum_{d|T}d^k\mu(\frac Td)
\]
首先后面这一堆东西显然是我们熟悉的狄利克雷卷积形式,而\(\mu\)和\(I_k\)都是积性函数,所以这后面一堆也是积性的,可以线性筛。就先设:
\[f(T)=\sum\limits_{d|T}d^k\mu(\lfloor\frac Td\rfloor)
\]
接下来问题来了:怎么筛?
首先我们线性筛大概分两部分:
第一部分,判断i是不是素数。
第二部分,筛掉i的倍数。
于是我们从这两部分下手。首先线性筛从2开始,所以特判1。手模一下,显然\(f(1)=1\)。
然后是第一部分。如果\(T\)是素数的话,那么\(T\)的因数只有1和他本身。手模一下,有
\[f(p)=\mu(p)+p^k=p^k-1
\]
然后讨论第二部分。首先既然\(f(T)\)是个积性函数,那么只要i不是prime[j]的倍数就直接嗯乘就可以了。即:
f[i*prime[j]=f[i]*f[prime[j]];
然后是\(prime[j]|i\)的情况。因为i*prime[j]刚好比i多一个质因子prime[j],所以根据积性函数性质,有
\[f(p^{x_i})=f(p^{x_i-1})*p
\]
于是直接搞就行了,别忘了处理前缀和。把线性筛代码放下面了。
void getmiu(){
f[1]=1;
for(int i=2;i<=5000000;i++){
if(!v[i]){
p[++p[0]]=i;
g[p[0]]=qpow(i,k);
f[i]=(g[p[0]]-1+mod)%mod;
}
for(int j=1;j<=p[0]&&i*p[j]<=5000000;j++){
v[i*p[j]]=true;
if(i%p[j]==0){
f[i*p[j]]=1ll*f[i]*g[j]%mod;break;
}
f[i*p[j]]=1ll*f[i]*f[p[j]]%mod;
}
}
for(int i=1;i<=5000000;i++)f[i]=(f[i-1]+f[i])%mod;
}
jzptab那个题和这个差不多,就是最后的函数不积性,但是也能线性筛。
DZY Loves Math那个线性筛稍微难一点,但是joke3579大佬埃式筛卡常过去了。
接下来是第三类:
(不要被黑题吓到,这原先是紫题)
题意:求
\[\prod_{i=1}^n\prod_{j=1}^mf(\gcd(i,j))
\]
其中\(f(x)\)为Fibonacci第x项。
斐波那契数列似乎没什么性质。没关系,先放着他,用里面的gcd来搞。
\[=\prod_{k=1}^n\prod_{i=1}^n\prod_{j=1}^mf(k)(\gcd(i,j)=k)
\]
按照套路,我们该把第二个和第三个\(\prod\)上的\(n\)变成\(\lfloor\frac nk \rfloor\)了,但是这是乘法,怎么办?
参考当时\(\sum\)的做法,当时我们由于少加了,直接在后面乘一个\(k^2\)。这里同理,多乘几次不就得了。多乘几次是什么?乘方!
\[=\prod_{k=1}^nf(k)^{\sum_{i=1}^{\lfloor\frac nk\rfloor}\sum_{j=1}^{\lfloor\frac mk\rfloor}(\gcd(i,j)=1)}
\]
然后我们把上面一堆东西整出来:
\[\sum_{i=1}^{\lfloor\frac nk\rfloor}\sum_{j=1}^{\lfloor\frac mk\rfloor}\gcd(i,j)=1
\]
不就是我们之前搞过的东西吗!
\[=\sum_{d=1}^{\lfloor\frac nk\rfloor}\mu(d)\lfloor\frac n{kd}\rfloor\lfloor\frac m{kd}\rfloor
\]
这个东西已经好很多了,卡常卡的好应该可以暴艹过去。但是如果你不是卡常大师应该会怒t所以继续套路:
设\(T=kd\),于是把这个东西再从指数上扔下来。我们之前把乘法换成\(\sum\)扔下来,现在指数也相应得搞成\(\prod\):
\[=\prod_{k=1}^nf(k)^{\sum_{d=1}^{\lfloor\frac nk\rfloor}\mu(d)\lfloor\frac nT\rfloor\lfloor\frac mT\rfloor}
\]
\[=\prod_{T=1}^n\prod_{d|T}f(d)^{\mu(\lfloor\frac Td\rfloor)\lfloor\frac nT\rfloor\lfloor\frac mT\rfloor}
\]
然后发现这一堆东西可以整个函数:
\[g(T)=\prod_{d|T}f(d)^{\mu(\lfloor\frac Td\rfloor)}
\]
但是指数上的东西似乎没法正常筛。那怎么办?
观察数据范围,1e6,似乎没有卡那么死。于是:
暴力枚举!
for(int i=1;i<=1000000;i++){
for(int j=1;i*j<=1000000;j++){
g[i*j]=1ll*g[i*j]*mypow(i,miu[j])%mod;
}
}
最后关于约数个数和这个题,给个柿子自己搞去:
\[d(ij)=\sum_{x|i}\sum_{y|j}[\gcd(i,j)=1]
\]
祝学的愉快!(虽然我巧了这两百多行的latex并不是很愉快)
后来的补充:我打算把其他几个题的题解一块放上去。所以排版风格可能不太一样。
幽灵乐团/莫比乌斯反演基础练习题
首先是题意:求
\[\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^p\left(\frac {\text{lcm}(i,j)}{\gcd(i,k)} \right)^{f(type)}\mod p
\]
的值。其中
\[f(0)=1,f(1)=i\times j\times k,f(2)=\gcd(i,j,k)
\]
\(70\)组询问,数据范围\(10^5\)。
题意简述完毕,下面是题解。
以下均默认\(n\le m\le k\)。
首先我们先把这个东西拆开。
\[\begin{aligned}
&\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^p\left(\frac {\text{lcm}(i,j)}{\gcd(i,k)} \right)^{f(type)}\\
=&\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^p\left(\frac {ij}{\gcd(i,j)\gcd(i,k)}\right)^{f(type)}\\
=&\frac{\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^p\left(ij\right)^{f(type)}}{\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^p\left(\gcd(i,j)\gcd(i,k)\right)^{f(type)}}
\end{aligned}
\]
于是我们的问题就变成了求
\[\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^pi^{f(type)}
\]
和
\[\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^p\gcd(i,j)^{f(type)}
\]
的值。
接下来分上下两边讨论。
type=1
上边:
\[\begin{aligned}
&\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^pi\\
=&mp\prod_{i=1}^ni\\
=&mp\times n!
\end{aligned}
\]
预处理阶乘即可。
下边:
\[\begin{aligned}
&\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^p\gcd(i,j)\\
=&p\prod_{d=1}^nd\prod_{i=1}^n\prod_{j=1}^m[\gcd(i,j)=d]\\
=&p\prod_{d=1}^nd\prod_{i=1}^{\lfloor \frac nd \rfloor}\prod_{j=1}^{\lfloor \frac md \rfloor}[gcd(i,j)=1]\\
=&p\prod_{d=1}^nd^{\sum_{i=1}^{\lfloor \frac nd \rfloor}\sum_{j=1}^{\lfloor \frac md \rfloor}[\gcd(i,j)=1]}\\
=&p\prod_{d=1}^nd^{\sum_{i=1}^{\lfloor \frac nd \rfloor}\sum_{j=1}^{\lfloor \frac md \rfloor}\sum_{e\mid\gcd(i,j)}\mu(e)}\\
=&p\prod_{d=1}^nd^{\sum_{e=1}^{\lfloor \frac nd \rfloor}\mu(e)\lfloor \frac nd \rfloor\lfloor \frac md \rfloor}\ \ \ \ \ \ \ \ \ T=ed\\
=&p\prod_{T=1}^n\left(\prod_{d\mid T}d^{\mu(\frac Td)}\right)^{\lfloor \frac nT \rfloor\lfloor \frac mT \rfloor}\\
\end{aligned}
\]
后边这一堆东西可以像数字表格那道题一样\(O(n\log n)\)预处理一下。(记得处理前缀积的逆元)
type=2
还是先来上边:
\[\begin{aligned}
&\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^pi^{ijk}
=&\prod_{i=1}^ni^{i\sum_{j=1}^mj\sum_{k=1}^nk}
\end{aligned}
\]
这玩意后边两个是等差数列,直接预处理就行。
下边:
\[\begin{aligned}
&\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^p\gcd(i,j)^{ijk}\\
=&\left(\prod_{i=1}^n\prod_{j=1}^m\gcd(i,j)^{ij}\right)^{\sum_{k=1}^pk}\\
=&\left(\prod_{d=1}^n\prod_{i=1}^n\prod_{j=1}^md^{ij}[\gcd(i,j)=d]\right)^{\sum_{k=1}^pk}\\
=&\left(\prod_{d=1}^n\prod_{i=1}^{\lfloor \frac nd \rfloor}\prod_{j=1}^{\lfloor \frac md \rfloor}d^{ijd^2}[\gcd(i,j)=1]\right)^{\sum_{k=1}^pk}\\
=&\left(\prod_{d=1}^nd^{d^2\sum_{i=1}^{\lfloor \frac nd \rfloor}\sum_{j=1}^{\lfloor \frac md \rfloor}[\gcd(i,j)=1]}\right)^{\sum_{k=1}^pk}\\
\end{aligned}
\]
太熟悉了,直接上最后结果。
\[=\left(\prod_{T=1}^n\left(\prod_{d\mid T}d^{T^2\mu(\frac Td)}\right)^{\sum_{i=1}^{\lfloor \frac nT \rfloor}i\sum_{j=1}^{\lfloor \frac mT \rfloor}j}\right)^{\sum_{k=1}^pk}
\]
中间的那个可以一块\(O(n\log n)\)筛出来(同样处理逆元),然后上面的指数又是一大堆等差数列,整除分块即可。
type=3
最ex的来了。一看这个东西十分诡异(反正官方题解的反演我看不懂而且大受震撼),于是考虑一点人类智慧解法。
我们考虑把它换成熟悉的样子,就是一堆\(\sum\)的那种,顺便不要在上面带着个三元的\(\gcd\)。怎么办?
我们不要看上边下边了,看原式。
\[\prod_{i=1}^n\prod_{j=1}^m\prod_{k=1}^p\left(\frac {\text{lcm}(i,j)}{\gcd(i,k)} \right)^{\gcd(i,j,k)}
\]
求个\(\ln\)把指数拉下来。
\[\begin{aligned}
&\sum_{i=1}^n\sum_{j=1}^m\sum_{k=1}^p\ln\left(\frac {\text{lcm}(i,j)}{\gcd(i,k)}\right)\gcd(i,j,k)\\
=&\sum_{i=1}^n\sum_{j=1}^m\sum_{k=1}^p\ln\left(\frac {\text{lcm}(i,j)}{\gcd(i,k)}\right)\sum_{d|\gcd(i,j,k)}\varphi(d)\\
=&\sum_{d=1}^n\varphi(d)\sum_{i=1}^{\lfloor \frac nd\rfloor}\sum_{j=1}^{\lfloor \frac md\rfloor}\sum_{k=1}^{\lfloor \frac pd\rfloor}\ln\left(\frac {\text{lcm}(id,jd)}{\gcd(id,kd)}\right)\\
=&\sum_{d=1}^n\varphi(d)\sum_{i=1}^{\lfloor \frac nd\rfloor}\sum_{j=1}^{\lfloor \frac md\rfloor}\sum_{k=1}^{\lfloor \frac pd\rfloor}\ln\left(\frac {\text{lcm}(i,j)}{\gcd(i,k)}\right)\\
\end{aligned}
\]
然后取个\(\exp\)。
\[\begin{aligned}
&\prod_{d=1}^n\left(\prod_{i=1}^{\lfloor \frac nd\rfloor}\prod_{j=1}^{\lfloor \frac md\rfloor}\prod_{k=1}^{\lfloor \frac pd\rfloor}\frac {\text{lcm}(i,j)}{\gcd(i,k)}\right)^{\varphi(d)}
\end{aligned}
\]
然后里面就是个type=1的情况了。复杂度通过积分可以得出是\(O(n^{\frac 34}\log n)\)。
结束。
一个人的数论
我至今为止都不知道为什么这个东西放到了莫反题单里.jpg
好了开始
题解 一个人的数论
前置知识:伯努利数
题意:求
\[\sum_{i=1}^ni^k[\gcd(i,n)=1]
\]
其中n以整数唯一分解形式给出(所以巨大)
首先我们按照惯例,还是先按照板子搞他一波:
\[=\sum_{i=1}^ni^k\sum_{d|\gcd(i,n)}\mu(d)
\]
很板子的提前搞一波
\[=\sum_{d|n}\mu(d)d^k\sum_{i=1}^{\frac nd}i^k
\]
然后我们发现这个东西好像没法搞了 于是?
1.暴力!期望得分:10(第一个点n<=1e5)
2.根据我们前面伯努利数的推导过程,发现后面这个东西不就是个等幂求和吗
于是可以推知这是个关于\(\frac nd\)的k+1次的多项式
于是设这个多项式是
\[\sum\limits_{i=1}^{k+1}f_i(\frac nd)^i
\]
接着搞原柿子
\[=\sum_{d|n}\mu(d)d^k\sum\limits_{i=1}^{k+1}f_i(\frac nd)^i
\]
\[=\sum_{i=1}^{k+1}f_in^i\sum_{d|n}\mu(d)d^{k-i}
\]
然后前面的东西就可以直接搞了。具体的说:首先递推伯努利数(设为B),递推式
\[B_0=1
\]
\[\sum_{i=0}^nC_{n+1}^iB_i=0(n>0)
\]
\[\sum_{i=0}^{n-1}i^m=\frac 1{n+1}\sum_{j=0}^nC_{n+1}^jB_jn^{m+1-j}
\]
接下来讨论后面的东西。
\[\sum_{d|n}\mu(d)d^{k-i}
\]
这个东西显然是积性的,所以我们可以枚举每个质因数,即
\[\prod_{j=1}^w\sum_{e=1}^{a_j}\mu(p_j^e)(p_j^e)^{k-i}
\]
然后发现:\(\mu\)只有当j=0或1时有意义,所以可以直接变成:
\[\prod_{j=1}^w1-p_i^{k-i}
\]
所以这个东西就可以每次\(O(w)\)的搞了。
然后预处理伯努利数就行了。代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
const int mod=1000000007;
int n=1,d,w,ans,jc[110],inv[110],b[110],p[1010],a[1010],g[110];
//jc是阶乘 inv是阶乘逆元(处理组合数用) g是题解中的f
int C(int n,int m){
return 1ll*jc[n]*inv[n-m]%mod*inv[m]%mod;
}
int qpow(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return ans;
}
//f是后面讨论的那个O(w)的函数
int f(int x){
if(x==-1)x=mod-2;
int ans=1;
for(int i=1;i<=w;i++)ans=1ll*ans*(1-qpow(p[i],x)+mod)%mod;
return ans;
}
//预处理伯努利数
void get(){
jc[1]=inv[1]=jc[0]=inv[0]=1;
for(int i=2;i<=105;i++){
jc[i]=1ll*jc[i-1]*i%mod;
inv[i]=qpow(jc[i],mod-2);
}
b[0]=1;
for(int i=1;i<=105;i++){
int ans=0;
for(int j=0;j<i;j++)ans=(ans+1ll*C(i+1,j)*b[j])%mod;
b[i]=(-(1ll*ans*qpow(i+1,mod-2)%mod)+mod)%mod;
}
for(int i=0;i<=d;i++)g[d+1-i]=1ll*C(d+1,i)*b[i]%mod*qpow(d+1,mod-2)%mod;
}
int main(){
scanf("%d%d",&d,&w);
get();
for(int i=1;i<=w;i++){
scanf("%d%d",&p[i],&a[i]);
n=1ll*n*qpow(p[i],a[i])%mod;
}
int ret=1;
for(int i=1;i<=d+1;i++){
ret=1ll*ret*n%mod;
ans=(ans+1ll*f(d-i)*g[i]%mod*ret)%mod;
}printf("%d",ans);
return 0;
}
当然你也可以跑一遍拉格朗日插值然后求出每个系数来。懒了,不写了。
实际上伯努利数的EGF是\(\frac x{e^x-1}\),可以直接多项式\(\exp\)然后求逆推出前\(k\)项,更优雅一点。不过懒得搞了。