莫比乌斯反演

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\)

1.P3455

题面:求

\[\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.一些不一样的东西

P2257 YY的GCD

题意:求

\[\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];
}

结束。

当然,也有一些题的函数可以线性筛出来。比如下题:

P4449 于神之怒加强版

题意:

\[\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大佬埃式筛卡常过去了。

接下来是第三类:

3.P3704 数字表格

(不要被黑题吓到,这原先是紫题)

题意:求

\[\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\)项,更优雅一点。不过懒得搞了。

posted @ 2022-09-03 11:42  gtm1514  阅读(22)  评论(0编辑  收藏  举报