组合数学,容斥原理与反演
这一篇是一个专题总结,可能会写很久,希望不会咕掉
一.组合数学:
①.基本公式:
1.排列数公式Amn=n!(n−m)!Amn=n!(n−m)!,表示从nn个元素中选出mm个元素并进行全排列的方案数
特别的,当m=nm=n时,有Ann=n!Ann=n!(规定0!=10!=1)
2.组合数公式Cmn=n!m!(n−m)!Cmn=n!m!(n−m)!,表示从nn个元素中选出mm个元素的方案数
排列与组合的关系:Amn=Cmnm!Amn=Cmnm!
3.组合数常见的等式:
(1).组合数的递推公式
Cmn=Cm−1n−1+Cmn−1Cmn=Cm−1n−1+Cmn−1
基于这一等式,产生了杨辉三角:
1
1 1
1 2 1
1 3 3 1
...
杨辉三角第ii行第jj列表示CjiCji(因此下标必须从00开始计数)
(2).杨辉三角某一行的求和公式:
∑ni=0Cin=2n∑ni=0Cin=2n
这一公式比较常用
(3).杨辉三角某一行的平方和公式:
∑ni=0(Cin)2=Cn2n∑ni=0(Cin)2=Cn2n
(4).组合数的奇偶求和公式:
C0n+C2n+...=C1n+C3n+...=2n−1C0n+C2n+...=C1n+C3n+...=2n−1
(5).组合数求和公式:
∑ni=mCmi=Cm+1n+1∑ni=mCmi=Cm+1n+1
代入上述递推式即可证明
(6).组合数的卷积公式:
∑ki=0CimCk−in=Ckn+m∑ki=0CimCk−in=Ckn+m
(7).组合数的对称性:
Cmn=Cn−mnCmn=Cn−mn
从nn个元素中取出mm个拿走等价于从nn个元素中取出n−mn−m个留下
4.卢卡斯定理:
Cmn≡CmmodpnmodpCm/pn/pCmn≡CmmodpnmodpCm/pn/p modmod pp
5.拓展卢卡斯定理的诡异结论:
若pp为一个奇质数,对任意k∈N∗k∈N∗,有:∏pki=1[gcd(i,p)≡1]i≡pk−1∏pki=1[gcd(i,p)≡1]i≡pk−1 modmod pkpk
当p=2p=2时,对任意k≤3k≤3,有:∏pki=1[gcd(i,p)≡1]i≡1∏pki=1[gcd(i,p)≡1]i≡1 modmod pkpk
(剩下那俩你算一下就好,k=2k=2时右侧是33)
②.二项式定理:
1.基本公式:
(x+y)n=∑ni=0Cinxiyn−i(x+y)n=∑ni=0Cinxiyn−i
2.有关推论:
(1).
令y=1y=1,得:
(x+1)n=∑ni=0Cinxi(x+1)n=∑ni=0Cinxi
然后对上式左右求导,得到:
n(x+1)n−1=∑ni=1iCinxi−1n(x+1)n−1=∑ni=1iCinxi−1
再令x=1x=1,得:
n2n−1=∑ni=1iCinn2n−1=∑ni=1iCin
发现右侧从00开始无影响,也即:
n2n−1=∑ni=0iCinn2n−1=∑ni=0iCin
不过更常见的是左右互化的应用。
(2).
令y=1y=1,得:
(x+1)n=∑ni=0Cinxi(x+1)n=∑ni=0Cinxi
然后对上式左右积分,得:
∫(x+1)ndx=∫∑ni=0Cinxidx∫(x+1)ndx=∫∑ni=0Cinxidx
展开得:
1n+1(x+1)n+1+C=∑ni=01i+1Cinxi+11n+1(x+1)n+1+C=∑ni=01i+1Cinxi+1
再令x=1x=1,,求出常数项,得:
2n+1−1n+1=∑ni=0Cini+12n+1−1n+1=∑ni=0Cini+1
仍然可以左右互化
这两个是比较常用的结论
二.序列的生成函数:
生成函数在计算方案数以及计算递推公式时都有很大的作用
①.基本定义:
给出序列{anan}={a0,a1,a2...ana0,a1,a2...an},构造一个函数(或者多项式)F(x)=a0+a1x+a2x2+...+anxnF(x)=a0+a1x+a2x2+...+anxn,则这个函数称作这个序列的生成函数(也叫母函数)
例:序列{1,1,1....1,1,1....}的生成函数是F(x)=1+x+x2+...F(x)=1+x+x2+...
可以看到,对于一个无穷数列,其生成函数自然会有无穷项
但是我们在解决问题时显然不可能讨论一个有无穷项的函数,而且这种函数的运算是极其困难的,因此我们考虑对这种函数进行化简:
(在化简这里有两种说法,这两种说法都能得出最后的结果,因此对于我这种蒟蒻暂且认为这二者等价,如果有大佬发现问题请及时讲解,谢谢!)
1.来自大部分资料的观点:
对于一个函数F(x)=1+x+x2+...F(x)=1+x+x2+...,可以发现这是一个等比数列求和的形式,由于在生成函数中真正体现数列性质的是每一项前的系数,而自变量本身的取值则意义不大,大部分时候我们不需要也不应该对这个自变量进行赋值,因此我们不妨给定一个定义域x∈(0,1)x∈(0,1),这样基于无穷递缩等比数列求和公式(∑∞i=0qi=11−q(q∈(0,1)∑∞i=0qi=11−q(q∈(0,1))立刻可以得出该函数的一个变形:F(x)=1+x+x2+...=11−xF(x)=1+x+x2+...=11−x
2.来自一个ppt的观点:
对于一个多项式,给出记法F(x)F(x) modmod xnxn表示F(x)F(x)在只保留次数低于nn的项之后剩余的部分
那么仍然套用等比数列求和公式(虽然不是递缩的不一定收敛但保证x!=1x!=1公式还是可以用的嘛)
可以写出:F(x)=1−xn1−xF(x)=1−xn1−x
当n−>∞n−>∞时,对任意的mm,一定有:1−xn1−x1−xn1−x modmod xm=11−xxm=11−x
因此F(x)=1+x+x2+...=11−xF(x)=1+x+x2+...=11−x
(这两种观点我个人认为都是在n−>∞n−>∞时令xn=0xn=0基于等比数列求和给出的,因此最后导出的结果一致,至于中间理解...见仁见智吧,我个人更喜欢第一种理解方式)
无论如何,我们已经做出第一个生成函数了
可是...这玩意有啥用?
②.实际应用——计算方案
问题:
设物品AA共有nn种价格,每种价格ii有aiai个物品
设物品BB共有mm种价格,每种价格ii有bibi个物品
求:已知总花费ww,在AA,BB两种物品中各购买一件物品,问总方案数?
(sb水题)
设物品AA选用的价格为ii,则与之对应的物品个数即为aiai,那么物品BB选用的价格即为w−iw−i,与之对应的物品个数为bibi,因此这一种的贡献即为aibw−iaibw−i
因此总贡献即为∑wi=0aibw−i∑wi=0aibw−i
(我会FFT,NTT!!!)
于是目测这个问题已经解决了
(好像没用上生成函数嘛)
但是,如果我们换个角度思考,对序列{anan},{bmbm}分别构造生成函数F(x)=∑wi=0aixiF(x)=∑wi=0aixi,G(x)=∑wi=0bixiG(x)=∑wi=0bixi,那么上面的答案不就是F(x)F(x)与G(x)G(x)做卷积后xnxn这一项前面的系数嘛!
(我不用生成函数也能看出来!)
如果我们有200个序列有各自的要求呢?
emmmmm.....
好像问题有点大...
但是,如果我们用生成函数,无论有多少个序列,最后也都是把这一坨东西乘起来就行了嘛
好像问题不大了...
可是...如果我们给出的数列有无穷项呢?
总不能跑无穷的FFT吧...
问题好像又出来了...
但是,如果仔细想想,怎么会让你做一个又没有递推(通项)又无穷的数列嘛!
这不是难为人吗
因此,如果一个数列有递推或者通项,那么生成函数可以借助上面的形式去化简啊
可是...我们最后要的是生成函数中某一项的系数,都变成这种诡异的分式怎么找最后的答案嘛!
不要忘了,上面我们做的都是等式,等式左右两侧可以互换的啊!
因此如果我们最后能求出一个分式的结果,那我们就能反向导出一个多项式!
因此我们的核心问题就在于怎么快速双向推导
我们有前辈的经验!
两个常见的模型:
F(x)=1+xa+x2a+...=11−xaF(x)=1+xa+x2a+...=11−xa
在有限项下的特殊情况:
F(x)=1+xa+x2a+...+xna=1−x(n+1)a1−xaF(x)=1+xa+x2a+...+xna=1−x(n+1)a1−xa
(注意!无限项与有限项是有本质区别的,因此有限项不应该套成无限项的公式)
另一个模型:
F(x)=∑∞i=0Ck−1i+k−1xi=1(1−x)kF(x)=∑∞i=0Ck−1i+k−1xi=1(1−x)k
(以上内容不加证明直接给出)
下面给出一道例题:
题解看这里
③.实际应用——计算数列的通项:
当然了,生成函数还有别的用处,比如用来求个通项之类的,最典型的例子就是斐波那契数列通项的计算,通常用的是特征根法,但是生成函数是一个适用范围更广的方法
1.给出序列f(n)=af(n−1)f(n)=af(n−1)(f(0)=1f(0)=1),求该序列的通项
这不是等比数列么
从这里开始我觉得更好理解一些
首先直接构造这一序列的生成函数:
G(x)=∑∞i=0f(i)xiG(x)=∑∞i=0f(i)xi
根据递推式,我们应当左右乘一个axax,于是得到:
axG(x)=∑∞i=0af(i)xi+1axG(x)=∑∞i=0af(i)xi+1
根据递推式,af(i)=f(i+1)af(i)=f(i+1),得到:
axG(x)=∑∞i=0f(i+1)xi+1axG(x)=∑∞i=0f(i+1)xi+1
上下做差,得到:
(1−ax)G(x)=f(0)x0=1(1−ax)G(x)=f(0)x0=1
移项得:
G(x)=11−axG(x)=11−ax
发现就是我们上面提到过的一个等比数列求和的模型(只不过公比变成了axax),于是立刻还原成等比数列求和的形式:
G(x)=1+ax+(ax)2+...G(x)=1+ax+(ax)2+...
也就是
G(x)=1+ax+a2x2+a3x3+...G(x)=1+ax+a2x2+a3x3+...
那么xixi前的系数即为aiai,也即f(i)=aif(i)=ai
(这玩意用生成函数求怕不是闲的)
你对生成函数的力量一无所知
2.给出序列f(n)=f(n−1)+f(n−2)f(n)=f(n−1)+f(n−2)(f(0)=0,f(1)=1f(0)=0,f(1)=1),求该序列的通项
这是斐波那契数列嘛
我会矩阵乘法!可我问的是通项
仍然按照套路来,构造一个生成函数G(x)=∑∞i=0f(i)xiG(x)=∑∞i=0f(i)xi
那么基于递推,显然要做两次变形:
左右乘xx,得到:
xG(x)=∑∞i=0f(i)xi+1xG(x)=∑∞i=0f(i)xi+1
左右乘x2x2,得到:
x2G(x)=∑∞i=0f(i)xi+2x2G(x)=∑∞i=0f(i)xi+2
后两个表达式求和,得到:
(x+x2)G(x)=∑∞i=0f(i)xi+1+∑∞i=0f(i)xi+2(x+x2)G(x)=∑∞i=0f(i)xi+1+∑∞i=0f(i)xi+2
也就是:
(x+x2)G(x)=∑∞i=1[f(i)+f(i−1)]xi+1(x+x2)G(x)=∑∞i=1[f(i)+f(i−1)]xi+1
根据递推公式,可以求得:
(x+x2)G(x)=∑∞i=1f(i+1)xi+1(x+x2)G(x)=∑∞i=1f(i+1)xi+1
再用第一个表达式去减:
(1−x−x2)G(x)=f(1)x1(1−x−x2)G(x)=f(1)x1
移项可得:
G(x)=x1−x−x2G(x)=x1−x−x2
问题来了:这玩意怎么变回多项式形式?
我们只会上面那两种原式形式啊!
没有关系,我们做一个转化就好。
我们看看,能不能将上述表达式转化成G(x)=A1−ax+B1−bxG(x)=A1−ax+B1−bx的形式
那么首先整理一下分母,把分母写成(1−ax)(1−bx)(1−ax)(1−bx)这种形式
如果我令上式为0,可以求得x1=1ax1=1a,x2=1bx2=1b
那么求解分母1−x−x2=01−x−x2=0这个二次方程,解得:
x1=−1+√52x1=−1+√52,x2=−1−√52x2=−1−√52
那么对应一下,就得到了:
a=√5+12a=√5+12,b=−√5+12b=−√5+12
于是变形得到:
A1−1+√52x+B1−1−√52xA1−1+√52x+B1−1−√52x
那么再通分一下,得到:
A[1−1−√52x]+B[1−1+√52x]1−x−x2A[1−1−√52x]+B[1−1+√52x]1−x−x2
(不要担心这个式子,因为他在一秒钟之内就会消失)
与原来的生成函数对应一下,发现原来的分子是xx,因此我们整理之后立刻可以列出一个二元一次方程组,即要求常数项为00,一次项系数为11的一个方程组
也就是:
A+B=0A+B=0
−1−√52A−1+√52B=1−1−√52A−1+√52B=1
解之,得:
A=1√5,B=−1√5A=1√5,B=−1√5
那么也就是:
G(x)=1√511−1+√52x−1√511−1−√52xG(x)=1√511−1+√52x−1√511−1−√52x
那不就相当于两个等比数列乘系数相加了嘛!
于是通项也就写出来了:f(n)=1√5[(1+√52)n−(1−√52)n]f(n)=1√5[(1+√52)n−(1−√52)n]
这个表达式的神奇之处也在于,即使里面充满了√5√5,你算出来的结果也一定是一个整数!
这就是生成函数的力量。
三.常见的模型结论:
①.卡特兰数问题:
模型1:给出nn个0和nn个1,将他们排成一个长度为2n2n的序列,问有多少种排列方式使得在该序列的任意前缀中00的个数不少于11的个数?
模型2:给出nn对括号,问有多少种合法的括号序列(将左括号看做"0",右括号看做“1”,问题和模型1等价)?
模型3:在一个n∗nn∗n的网格中从左下角向右上角走,只能向上或向右且不能越过对角线的方案数?
模型4:一个有n+1n+1个叶节点的不同二叉树种类数?(或有nn个节点的二叉树种类数?)
模型5:在圆上有2n2n个节点,两两连线
这些问题的答案都是卡特兰数的第nn项
卡特兰数列记作cncn(c0=1c0=1)
他的通项:cn=Cn2n−Cn−12ncn=Cn2n−Cn−12n=1n+1Cn2n1n+1Cn2n
他的递推:cn+1=2(2n+1)n+2cncn+1=2(2n+1)n+2cn
递推的卷积形式:cn+1=∑ni=0cicn−icn+1=∑ni=0cicn−i(注意左右互化,推出右侧这种形式的东西考虑卡特兰数)
生成函数形式:F(x)=1−√1−4x2xF(x)=1−√1−4x2x
②.第一类斯特林数:
第一类斯特林数S1(n,k)S1(n,k)表示将nn个数的序列划分为kk个圆排列的方案数
递推式:S1(n,k)=S1(n−1,k−1)+(n−1)S1(n−1,k)S1(n,k)=S1(n−1,k−1)+(n−1)S1(n−1,k)
递推原理:考虑第nn个元素的放法:首先是单独形成一个圆排列,或者在放在原先的圆排列中任意一个元素之后
生成函数形式:第nn行斯特林数的生成函数为F(x)=∏n−1i=0(x+i)F(x)=∏n−1i=0(x+i)
据说可以分治FFT求,不过既然这样的话应该也可以多项式求逆水一水的说...
但是好像有个倍增的搞法,推导过程如下:
考虑我们已知Fn(x)=∏n−1i=0(x+i)Fn(x)=∏n−1i=0(x+i)
那么立刻可以知道F2n(x)=Fn(x)Fn(x+n)F2n(x)=Fn(x)Fn(x+n)
我们同时还知道Fn(x)=∑ni=0aixiFn(x)=∑ni=0aixi
那么Fn(x+n)=∑ni=0ai(x+n)iFn(x+n)=∑ni=0ai(x+n)i
二项式定理展开后面那个东西:
Fn(x+n)=∑ni=0ai∑ij=0Cjixini−jFn(x+n)=∑ni=0ai∑ij=0Cjixini−j
改变一下枚举顺序:
Fn(x+n)=∑ni=0xi∑nj=iajCijnj−iFn(x+n)=∑ni=0xi∑nj=iajCijnj−i
打开组合数
Fn(x+n)=∑ni=0xi∑nj=iajj!i!(j−i)!nj−iFn(x+n)=∑ni=0xi∑nj=iajj!i!(j−i)!nj−i
再整理一下后面那一坨
Fn(x+n)=∑ni=0xii!∑nj=iajj!nj−i(j−i)!Fn(x+n)=∑ni=0xii!∑nj=iajj!nj−i(j−i)!
后面是个卷积,直接算出来,然后乘系数即可
这样就可以倍增了
性质:
∑nk=0S1(n,k)=n!∑nk=0S1(n,k)=n!
③.第二类斯特林数:
第二类斯特林数S(n,k)S(n,k)表示将nn个不同元素划分为kk个集合的方案数
递推式:S(n,k)=S(n−1,k−1)+kS(n−1,k)S(n,k)=S(n−1,k−1)+kS(n−1,k)
组合意义下的写法:S(n,k)=1k!∑ki=0(−1)iC(k,i)(k−i)nS(n,k)=1k!∑ki=0(−1)iC(k,i)(k−i)n
这样的话,考虑快速求斯特林数的方法:
展开后面的组合数:
S(n,k)=1k!∑ki=0(−1)ik!i!(k−i)!(k−i)nS(n,k)=1k!∑ki=0(−1)ik!i!(k−i)!(k−i)n
然后扔到前面去:
S(n,k)=∑ki=0(−1)ii!(k−i)n(k−i)!S(n,k)=∑ki=0(−1)ii!(k−i)n(k−i)!
这就是卷积了嘛
性质:
mn=∑mi=0CimS(n,i)i!mn=∑mi=0CimS(n,i)i!
四.容斥原理:
①.基础表达式:
设|A||A|表示集合|A||A|的元素个数,则有:
|A1∪A2∪...∪An|=∑(−1)m−1|Aa1∩Aa2∩...∩Aam||A1∪A2∪...∪An|=∑(−1)m−1|Aa1∩Aa2∩...∩Aam|
这是最基础的表达式,任何一种形式的反演都可以看做容斥原理作用于某一个模型下的结果
②.关于“至少”与“恰好”的转化:
一个都没有=至少有0个-至少有一个+至少有两个...(按奇偶进行容斥)
五.反演:
①.基础反演原理:
所有反演都是容斥原理的某种体现,是容斥原理作用于某个具体模型下得到的结果,当然大部分也都可以通过直接代入证明
反演的实质:
如果我们已知一种递推关系fi=∑ij=0aijgjfi=∑ij=0aijgj,那么我们试图构造出用ff计算gg的递推式的过程就是反演,即:
已知fi=∑ij=0aijgjfi=∑ij=0aijgj,则可推出gi=∑ij=0a′ijfjgi=∑ij=0a′ijfj
那么我们考虑这个过程的本质:这个过程本质上是提供了一组线性方程
(a00g0+0+0+...0=f0a10g0+a11g1+0+...0=f1...an0g0+an1g1+an2g2+...anngn=fn)⎛⎜ ⎜ ⎜⎝a00g0+0+0+...0=f0a10g0+a11g1+0+...0=f1...an0g0+an1g1+an2g2+...anngn=fn⎞⎟ ⎟ ⎟⎠
利用高斯消元,我们当然可以在已知ff的情况下求解出gg
当然,由于这个矩阵本身就是个下三角,因此高斯消元其实只需回代,时间复杂度O(n2)O(n2)
但是这个复杂度仍然并不优秀,我们关心的是是否可以快速的求解出用ff表示gg之后这个递推式对应的系数
因此我们需要一些推导
②.反演的判别性原理:
考虑上面的表达式:
fi=∑ij=0aijgjfi=∑ij=0aijgj
我们想要求出满足gi=∑ij=0a′ijfjgi=∑ij=0a′ijfj的a′a′矩阵
那么我们首先定义一个函数:令δ(x,y)=[x==y]δ(x,y)=[x==y],那么显然有表达式:
fi=∑ij=0δ(i,j)fjfi=∑ij=0δ(i,j)fj
代入上式,得:
∑ij=0aijgj=∑ij=0δ(i,j)fj∑ij=0aijgj=∑ij=0δ(i,j)fj
代入我们想求出的东西,得到:
∑ij=0aij∑jk=0a′jkfk=∑ij=0δ(i,j)fj∑ij=0aij∑jk=0a′jkfk=∑ij=0δ(i,j)fj
考虑左侧每个fkfk会被计算的次数,更换一下枚举顺序,得到:
∑ij=0fj∑ik=jaika′kj=∑ij=0δ(i,j)fj∑ij=0fj∑ik=jaika′kj=∑ij=0δ(i,j)fj
左右系数对应一下,就得到了:
∑ik=jaika′kj=δ(i,j)∑ik=jaika′kj=δ(i,j)
所有反演一定满足这一表达式,所有反演的证明也可以基于这一表达式给出
③.莫比乌斯反演:
1.背景知识:狄利克雷卷积
设f,g,hf,g,h是三个数论函数,定义运算*表示若f=g∗hf=g∗h,则f(i)=∑d|ig(d)h(id)f(i)=∑d|ig(d)h(id)
2.基础表达式:
若已知f(i)=∑d|ig(d)f(i)=∑d|ig(d),则g(i)=∑d|iμ(d)f(id)g(i)=∑d|iμ(d)f(id)
3.常见结论:
ϕ(n)=∑d|nμ(d)ndϕ(n)=∑d|nμ(d)nd
∑d|nμ(d)=[n==1]∑d|nμ(d)=[n==1]
n=∑d|nϕ(d)n=∑d|nϕ(d)
4.常见套路:
(1).数论分块:
考虑一个数nn,对任意i∈[1,n]i∈[1,n],nini向下取整的取值数量是O(√(n))O(√(n))级别的,这个结论可以推广至两元,即对于两个数n,mn,m,对任意i∈[1,n]i∈[1,n],定义二元组(ni,mi)(ni,mi),则这样不同的二元组的个数级别是O(√(n))O(√(n))的
(伪)代码:
int last=0; for(int i=1;i<=n;i=last+1) { last=min(n/(n/i),m/(m/i)); ans+=f(last); }
(2).枚举倍数:
考虑我们已知一种与约数有关的表达式,f(n)=∑d|nkgdf(n)=∑d|nkgd,kk为常数,那么我们需要计算出[1,105][1,105]的ff值,如何计算?
如果直接枚举约数,时间复杂度为O(n√n)O(n√n),虽然能过但常数巨大,如果这个问题仅仅是一个庞大问题的子问题的话那么这个时间消耗就不合算了
但是我们考虑另一个问题:∑ni=11i=lnn∑ni=11i=lnn(调和级数求和)
那么我们如果直接枚举所有数的倍数的话,时间复杂度就是∑ni=1ni=nlnn∑ni=1ni=nlnn,这个复杂度就是很优秀的了
因此我们可以转化问题,将枚举约数转化成枚举倍数!
(3).调换顺序:
更换枚举顺序,有时后面的部分就可以预处理或快速计算了
(4).线性筛:
线性筛可以筛出大量的信息,积性函数基本都支持线性筛
在筛非常见积性函数时,我们需要知道这几个问题:
首先,这个函数是完全积性还是不完全积性?
这个问题很重要,如果是完全积性函数可以随便算了
然后,我们能不能由f(pk)f(pk)快速计算出f(pk+1)f(pk+1)?
这一点也很重要,如果我们不能实现这一点的话,就没有办法在不互质的情况下更新答案了
(5).杜教筛
杜教筛是这样一种筛法:对于一个数论函数ff,我们希望快速求出其前缀和
但是我们的数据范围要求很大,即使线性筛也难以处理
这时我们就需要考虑杜教筛了
杜教筛的思想:寻找一个数论函数gg,令h=f∗gh=f∗g,且hh的前缀和可以快速计算(最好是O(1)O(1)),那么我们导一导式子就可以推出ff的前缀和了
首先考虑ff的前缀和Sn=∑ni=1f(i)Sn=∑ni=1f(i)
然后考虑f∗gf∗g的前缀和∑ni=1f∗g(i)∑ni=1f∗g(i)
然后整理后面那堆东西:∑ni=1∑d|if(d)g(id)∑ni=1∑d|if(d)g(id)
按照套路改变枚举顺序,得到:
∑nd=1g(d)∑ndj=1f(j)∑nd=1g(d)∑ndj=1f(j)
也就是∑nd=1g(d)Snd∑nd=1g(d)Snd
接下来考虑我们要求出的是SnSn,也就是在d=1d=1时的情况,那么我们考虑d=1d=1时,g(1)Sng(1)Sn的值
可以发现,这个值就是∑ni=1g(i)Sni−∑ni=2g(i)Sni∑ni=1g(i)Sni−∑ni=2g(i)Sni
于是我们给出杜教筛的表达式:g(1)Sn=∑ni=1g(i)Sni−∑ni=2g(i)Snig(1)Sn=∑ni=1g(i)Sni−∑ni=2g(i)Sni
这有啥用?
我们转化一下,也就是g(1)Sn=∑ni=1(f∗g)(i)−∑ni=2g(i)Snig(1)Sn=∑ni=1(f∗g)(i)−∑ni=2g(i)Sni
那么我们知道,前面那个东西我们让他容易求,后面那堆可以数论分块之后递归求解
注意记忆化,用map或hash表存一下
④.二项式反演:
1.基本表达式:
若已知f(n)=∑ni=0(−1)iCingif(n)=∑ni=0(−1)iCingi,则有:g(n)=∑ni=0(−1)iCinf(i)g(n)=∑ni=0(−1)iCinf(i)
一个更常见的公式:
已知f(n)=∑ni=0Cing(i)f(n)=∑ni=0Cing(i),可以推知g(n)=∑ni=0(−1)n−iCinf(i)g(n)=∑ni=0(−1)n−iCinf(i)
2.常见应用:将“正好有...”转化为“至少有....”
这里要用到的一个推论:若f(k)=∑ni=kCkig(i)f(k)=∑ni=kCkig(i),则g(k)=∑ni=k(−1)i−kCkif(i)g(k)=∑ni=k(−1)i−kCkif(i)
⑤.单位根反演:
1.基本表达式:
设f(x)=∑ni=0aixif(x)=∑ni=0aixi
则有∑ni=0ai[d|i]=1d∑d−1p=0f(wpd)∑ni=0ai[d|i]=1d∑d−1p=0f(wpd)
在FFTFFT中会用到的形式:
fi=∑n−1j=0wi∗jnngjfi=∑n−1j=0wi∗jnngj可以推得gi=∑n−1j=0w−i∗jnnfjgi=∑n−1j=0w−i∗jnnfj
本质形式:
1n∑n−1i=0wd∗in=[n|d]1n∑n−1i=0wd∗in=[n|d]
2.常见应用:
求下标取模某个数为定值的数之和
⑥.斯特林反演:
1.基本表达式:
若f(n)=∑ni=0S(n,i)g(i)f(n)=∑ni=0S(n,i)g(i),则g(n)=∑ni=0(−1)n−kS1(n,i)f(i)g(n)=∑ni=0(−1)n−kS1(n,i)f(i)
其中S(n,i)S(n,i)表示第二类斯特林数,S1(n,i)S1(n,i)表示第一类斯特林数
2.常见应用:
我不知道...
六.多项式初步
①.多项式求逆:
问题:
已知一个次数为n−1n−1的多项式F(x)F(x),求一个多项式G(x)G(x)使得F(x)∗G(x)≡1F(x)∗G(x)≡1(modxnmodxn),所有运算在模998244353意义下进行
怎么搞?
先进行一点分析:
如果F(x)F(x)只有一项,那么G(x)G(x)里也只有一项,就是F(x)F(x)里那项的逆元
那么如果我们已知一个多项式H(x)H(x)满足F(x)∗H(x)≡1F(x)∗H(x)≡1(modmod xn2xn2)
很显然,根据要求,同时有:F(x)∗G(x)≡1F(x)∗G(x)≡1(modmod xn2xn2)
下式减上式,得到:
F(x)(G(x)−H(x))≡0F(x)(G(x)−H(x))≡0(modmod xn2xn2)
于是有
G(x)−H(x)≡0G(x)−H(x)≡0(modmod xn2xn2)
两边平方,可以得到:
(G(x)−H(x))2≡0(G(x)−H(x))2≡0 (modmod xnxn)
展开,得:
G(x)2+H(x)2−2G(x)H(x)≡0G(x)2+H(x)2−2G(x)H(x)≡0(modmod xnxn)
两边乘一个F(x)F(x),有:
F(x)G(x)2+F(x)H(x)2−2F(x)G(x)H(x)≡0F(x)G(x)2+F(x)H(x)2−2F(x)G(x)H(x)≡0(modmod xnxn)
根据要求,F(x)G(x)≡1F(x)G(x)≡1(modmod xnxn)
于是上式可以化简成:
G(x)+F(x)H(x)2−2H(x)≡0G(x)+F(x)H(x)2−2H(x)≡0(modmod xnxn)
移项,得到:
G(x)≡2H(x)−F(x)H(x)2G(x)≡2H(x)−F(x)H(x)2 (modmod xnxn)
这样就可以倍增求解了
②.多项式带余除法:
多项式求逆是多项式除法的基础,如果你不会多项式求逆,请看这里
问题:已知两个多项式F(x)F(x)(次数为n),G(x)G(x)(次数为m),求两个多项式Q(x)Q(x)与R(x)R(x),满足F(x)=G(x)Q(x)+R(x)F(x)=G(x)Q(x)+R(x),所有运算在模998244353意义下进行
推一发式子:
F(x)=G(x)Q(x)+R(x)F(x)=G(x)Q(x)+R(x)
用1x1x替代xx,得到:
F(1x)=G(1x)Q(1x)+R(1x)F(1x)=G(1x)Q(1x)+R(1x)
两边乘一个xnxn,得:
xnF(1x)=xmG(1x)xn−mQ(1x)+xnR(1x)xnF(1x)=xmG(1x)xn−mQ(1x)+xnR(1x)
对表达式F(x)=G(x)Q(x)+R(x)F(x)=G(x)Q(x)+R(x)进行分析,可以看到,若F(x)F(x)次数为n,G(x)G(x)次数为m,则Q(x)Q(x)次数为n−mn−m,R(x)R(x)次数不超过m-1
那么对自变量先取逆再乘一个最高次数等价于构造一个系数与原多项式恰好相反的多项式!
也即若F(x)=∑ni=0aixiF(x)=∑ni=0aixi,则xnF(1x)=∑ni=0an−ixixnF(1x)=∑ni=0an−ixi
我们记xnF(1x)=∑ni=0an−ixi=FT(x)xnF(1x)=∑ni=0an−ixi=FT(x)
那么上式可以简写成FT(x)=GT(x)QT(x)+RT(x)FT(x)=GT(x)QT(x)+RT(x)
可以发现,RT(x)RT(x)这个多项式前(n−m+1)(n−m+1)项的系数均为0!
因此如果我们在modmod xn−m+1xn−m+1意义下,可以立刻得出这个等式:
FT(x)≡GT(x)QT(x)FT(x)≡GT(x)QT(x)(modmod xn−m+1xn−m+1)
那么移项即得:
QT(x)≡FT(x)GT(x)QT(x)≡FT(x)GT(x)(modmod xn−m+1xn−m+1)
这样就求出了Q(x)Q(x),然后基于原表达式,可得:
R(x)=F(x)−G(x)Q(x)R(x)=F(x)−G(x)Q(x)
R(x)R(x)就算出来了
③.多项式开根:
问题:已知一个多项式F(x)F(x)次数为n−1n−1,求一个多项式G(x)G(x)使得(G(x))2≡F(x)(G(x))2≡F(x)(modmod xnxn)
(保证常数项为11)
仍然是推式子
首先,不难发现的是如果F(x)F(x)次数为0,那么G(x)=1G(x)=1
类似多项式求逆,我们倍增处理:
设已知H(x)2≡F(x)H(x)2≡F(x)(modmod xn2xn2)
那么有H(x)2−F(x)≡0H(x)2−F(x)≡0(modmod xn2xn2)
两边平方,得:
[H(x)2−F(x)]2≡0[H(x)2−F(x)]2≡0(modmod xnxn)
两边加上4H(x)2F(x)4H(x)2F(x),得到:
[H(x)2+F(x)]2≡4H(x)2F(x)[H(x)2+F(x)]2≡4H(x)2F(x)(modmod xnxn)
两边除掉4H(x)24H(x)2,得:
[H(x)2−F(x)]24H(x)2≡F(x)[H(x)2−F(x)]24H(x)2≡F(x)(modmod xnxn)
可以发现左边是一个完全平方的形式,那么我们整理一下,得到:
[H(x)2−F(x)2H(x)]2≡F(x)[H(x)2−F(x)2H(x)]2≡F(x)(modmod xnxn)
那么我们所求的G(x)G(x)不就出来了嘛
G(x)=H(x)2−F(x)2H(x)G(x)=H(x)2−F(x)2H(x)
用类似多项式求逆的方法递归求解即可
④.多项式对数:
问题:已知一个次数为n−1n−1的多项式F(x)F(x),求一个多项式G(x)G(x)使得G(x)≡ln(F(x))G(x)≡ln(F(x))(modmod xnxn)
(保证F(x)F(x)常数项为1)
这个比较简单:
两边求导,得:
G′(x)≡F′(x)F(x)G′(x)≡F′(x)F(x)(modmod xnxn)
右侧都已知,直接多项式求逆计算出来即可
然后两边做不定积分,本来会有一个常数项,但是考虑到ln(F(0))=ln1=0=Cln(F(0))=ln1=0=C,因此常数项直接为0即可
⑤.多项式exp:
问题:已知一个多项式F(x)F(x)次数为n−1n−1,求一个多项式G(x)G(x)满足G(x)≡eF(x)G(x)≡eF(x)(modmod xnxn)
保证F(x)F(x)常数项为00
好像有点困难...
首先有一个基础知识:
我们可以用牛顿迭代求出一个多项式的多项式零点
也即已知一个多项式F(x)F(x),可以利用牛顿迭代求出一个多项式G(x)G(x)满足F(G(x))≡0F(G(x))≡0(modmod xnxn)
为什么我们要知道这件事情?
假设我们已知了G0(x)≡eF(x)G0(x)≡eF(x)(modmod xn2xn2
那么我们需要求出的就是G0G0与G(x)G(x)的关系
首先,根据牛顿迭代公式,可得:
G(x)=G0(x)−F(G0(x)F′(G0(x))G(x)=G0(x)−F(G0(x)F′(G0(x))
(关于这个公式的来历,我在最下面有一个感性理解的部分)
但是这个嵌套的东西还是很闹心
那么我们从另一个方向再进行一些推导:
已知G(x)≡eF(x)G(x)≡eF(x)(modmod xnxn)
那么两边取对数
lnG(x)−F(x)≡0lnG(x)−F(x)≡0(modmod xnxn)
设H(G(x))≡lnA(x)−B(x)≡0H(G(x))≡lnA(x)−B(x)≡0 (modmod xnxn)
那么求导即得到H′(G0(x))≡G−10(x)H′(G0(x))≡G−10(x)
那么再回到上面的表达式:
G(x)=G0(x)−H(G0(x)H′(G0(x))G(x)=G0(x)−H(G0(x)H′(G0(x))
最后整理一遍,得到:
G(x)≡G0(x)[1−lnG0(x)+F(x)]G(x)≡G0(x)[1−lnG0(x)+F(x)](modmod xnxn)
这样就可以倍增去求了
关于牛顿迭代:
假设我们要求一个函数f(x)f(x)的零点,那么我们不妨假设这个零点是x0x0,然后将f(x)f(x)在x=x0x=x0处求导得f′(x0)f′(x0),计算出在这一点的切线
y=f′(x0)(x−x0)+f(x0)y=f′(x0)(x−x0)+f(x0)
接下来求出该切线与xx轴交点横坐标x1x1,那么x1x1的精度就比x0x0的精度好一倍(大概是这个意思吧)
我们计算出x1x1的表达式,可以发现x1=x0−f(x0)f′(x0)x1=x0−f(x0)f′(x0),那么这就是一个递推关系式,将未知数xx换为多项式G(x)G(x)即得回上式
⑥.多项式快速幂:
问题:已知一个次数为n−1n−1的多项式F(x)F(x),求一个多项式G(x)G(x)满足G(x)≡F(x)kG(x)≡F(x)k
这个...你需要多项式exp
直接推一发式子就可以了:
G(x)≡F(x)kG(x)≡F(x)k
G(x)≡elnF(x)kG(x)≡elnF(x)k
G(x)≡eklnF(x)G(x)≡eklnF(x)
这样写个多项式ln和多项式exp就可以了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY