Loading

多项式计数

Matrix - Tree 定理

需要知道的一些线性代数知识

线性相关

考虑 n 个向量 v1,v2vn,如果存在 (a1,a2,an)0 满足 a1v1+a2v2=0 那么称这 n 个向量线性相关,反之为线性独立。

行列式

对于一个 n×n 的矩阵 A

det(A)=σ:(n)A1,σ(1)A2,σ(2)An,σ(n)(1)inv(σ)

性质

  • 将第 i×a 加到第 j 列,det(A) 不变。
  • 交换两列,行列式值取反。
  • 某列全体 ×adet 变大 a 倍。

以上三个可以根据定义得到,并且对于行也成立。

同时行列式满足 det(A)=det(AT)。如果 det(A)0,那么所有列向量是线性无关的。

计算方式

观察三角矩阵的 det。会发现其值为 ai,i

考虑如果做一个类似高斯消元的过程让行列式变成三角矩阵。

可以讲一下大概怎么做,其实是非常平凡的,我们考虑一列一列消。对于第 i 列,只保留 [1,i] 行的内容。通过第一条性质可以轻松做到,举例:

|231134223|

先消第一行,那么对于第二行加上第一行所有的数 ×12 的结果,第三行加上第一行所有的数 ×1 的结果,得到:

|23103272012|

然后对于第二列做一样的操作,会发现因为前面都是 0 了,那么这些数是不会影响操作的。最后就会形成一个三角矩阵。

在需要取模非质数的时候,可以进行两行辗转相减,不做赘述。

矩阵树定理

对于图 G=(V,E),考虑

定义 Q 矩阵,满足:

  • Qi,i=degi
  • Qi,j=1,ij,(i,j)E
  • Qi,j=0,ij,(i,j)E

M1,1 为删掉 Q 中的第一行第一列,则 G 中的生成树个数就等于 det(M1,1)

Q 矩阵还有一个名字即 Kirchoff 矩阵。还可以写成 Q=DAD 为度数矩阵 A 为图的邻接矩阵。

如果有重边同样成立,将 1cntcnt 为之间的边数即可。

而且 Mi,i=Mj,j,i,j[1,n]


证明

证明是比较重要的, 因为后面题目需要用到一些证明的思想。

定义矩阵 E,其有 nm 列,满足 i 列的 u 项为 1v 项为 1。其中 (u,v)i 条边连接的点。

那么有 E×ET=Q,这个是好证明的。

FE 删掉第一行的矩阵,那么有

det(M1,1)=det(F×FT)=Sdet(FS)2

第二部运用了 Cauchy–Binet formula,即对于 n×m 矩阵 Am×n 矩阵 Bdet(AB)=Sdet(AS)det(BS) 其中 S 表示 {1,2,m} 的大小为 n 的一个子集。AS 表示取出这些对应列组成的矩阵,B 是取出这些对应行组成的矩阵。这里带入 F,FT 会发现 (FS)T=(FT)S,也就是说这两个的行列式是一样的,通过上面的行列式的性质可以得到。

引理:S 相当于在 m 里面选择 n1 条边。会发现,det(FS)=±1 当且仅当 S 构成生成树,否则 det(FS)=0

如果 S 存在环,那么显然这个环上面的所有边构成的列向量加起来是 0,也就是说 det(A)=0。对于第一部分的证明,可以感性观察,注意到交换行列不会影响行列式的绝对值,因此可以构造出来三角矩阵,且斜对角全部是 1

也就是说 Sdet(FS)2 就是对于生成树计数。


用法以及技巧

带权树

矩阵树可以求的是:

T1

同样还可以求:

TeTwe

可以把边的权值视为有 we 条重边,发现每一个生成树相当于没有重边的版本乘上权值。将对应的 Kirchoff 矩阵修改即可。

一些 DFT / IDFT 的算法

学多项式是一个很有意思的过程。开始的时候你会学习 FFT / NTT 知道怎么样通过 DFT / IDFT 快速计算多项式的各种操作。然后你会深入学习多项式的各种运算,比如求逆、exp,ln 等等。然后你会到这一个部分,你发现又回到了 DFT / IDFT 的一些操作之中,但是再次看这些东西的时候,你其实比刚开始学的时候有了更为深入的理解。有一种“反其本矣”的奇妙感觉。

Bluestein

一般在做 DFT 的时候,会将给定的多项式变成 2k 长度来操作,考虑这样一个问题:

给定 A(x),求 A(x)ω0,,ωn1 位置的点值。

转化,对于 b0bn1,令 bm=k=0n1ak×(ωm)k,有一个小技巧:

2mk=m2+(k1)2(mk)2

通过这个来整理一下式子,能够得到:

bm=ω12m2k=0n1akω12(k+1)212(mk)2

后面两个东西看起来很像一个卷积的形式,但是不标准,因为和事 m+1。经典平移一下,令 Bm+n=ω12m2bmAk=akω12(k+1)2,再令 Cj=ω12(jn)2,让 Av=0,v[n,m+n] 能够得到:

Bm+n=k=0n+mAkCm+nk

这就是标准卷积形式,其中的 A,C 都是很好得到的。

注意在小技巧部分,如果用 2mk=m2+k2(mk)2 看起来能够得到结果,但是这会导致 ω 的出现,这要求存在二次剩余。

Bluestein 还有一个优势就是可以做等比多点求值,且是 O(nlogn),比直接多项式多点求值要快。

I:JDU-4656

题面

给定 a,b,c,d,令 F(x)=i=1n1aixik[0,n)F(b×c2k+d)。取模 106+3

Sol

先推一下式子:

F(k)=i=1n1ai(b×c2k+d)i=i=1n1aij=0i(ij)bjc2kjdij=j=0n1bjc2kjj!i=jn1i!aidij(ij)!

pj=i=jnaii!dij(ij)!,这看起来就很能卷机的样子,搞一搞可以弄成:pnj=i=0njfnijgi 的形式。

对于前面那个东西,回顾一下刚才的东西,令 ω=c2k 就是一个等比多点求值的过程了。

注意这题要 MTT。

单位根反演

核心式子:

[n|k]=1ni=0n1ωnik

证明需要回顾一下单位根的性质,在多项式小记里面有,都是非常基础的。

  • 如果 kmodn=0,此时有 ωik=1 右边等于 1n×n=1 等于左边。
  • 如果 kmodn0,此时右边是等比数列求和,结果为 ωnkn1ωnk1,分子等于 0 且分母不等于 0。结果就是 0

这个是处理形如“只保留某个数的倍数项”问题的利器。直接来看例题。

II:白兔的 ?难

cnblogs 你这屏蔽我?

题面

给定 n,k 求:

0t<k,st=i=tnt[k|i](ni+t)

n10106,k=2m,m20

Sol

进行单位根反演:

st=i=tnt[k|i](ni+t)=i=tnt1kj=0k1ωkij(ni+t)=1ki=tntj=0k1ωkij(ni+t)

套路地交换求和项,然后进行一些提取。

st=1kj=0k1ωtji=tnt(ωi+t)j(ni+t)=1kj=0k1ωtji=0n(ωj)i(ni)=1kj=0k1ωtj(ωj+1)n

对于 DFT / IDFT 比较熟悉的选手能够看出来这部分就是一个 IDFT 过程(因为这刚好是一个 2v 的多项式)就是我们在知道了点表示法然后转回到系数表示法的过程,这个在多项式小记里面也有式子。写起来是比较简单的。

来看一道综合一点的套路题,也是可爱的兔子。

III:白兔之舞

题面

给定 (L+1)×n 个点,可以理解为 (L+1)n 列。对于一对点 (u1,v1),(u2,v2)u2>u1(u1,v1)(u2,v2) 之间有 W[v1][v2] 条不同的边。其他情况没有边。现在给定 x,k,y,有一只兔子从 (0,x) 开始,终点在 (?,y)。对于所有 0t<k,求有多少条不同的路径满足其长度 lenmodk=t,答案 modp

n3,L108,1k65536,pprime,k|(p1)

Sol

先考虑固定长度 i 有多少种从 (0,x)(?,y) 的方案,令这个问题答案为 fi。对于行,相当于选择一些行去走,即 (Li),行和列是独立的,令 G 为开始时候的矩阵,那么列的情况就应该是 G×Wi 的第 y 项,下面记为 (G×Wi)y。经典传球问题。那么有 fi=(Li)×(G×Wi)y,接下来就可以开始推式子了,令答案为 ans

anst=i=0L[k|(it)]fi=i=0L1kj=0k1ωkj(it)×(Li)×(G×Wi)y=(1k×j=0k1G×ωkjti=0L(ωkj)i×(Li)×Wi)y=(1k×j=0k1G×ωkjt(ωkj×W+I)L)y

这里已经看到胜利的曙光了,但是这个题有点问题在于并没有保证 L=2v 不能走捷径,但是问题也不大,相当于要长度不为 2v 的单位根的点值,老老实实用 Bluestein 做。但是还要注意要写 MTT,因为模数不确定。

感觉这题的评分点全在套路上了,推式子就是纯套路。

循环卷积

这部分的定义需要注意一下,不要和普通的线性卷积混淆。循环卷积如其名,为:

Cr=A(x)B(x)=p,q[(p+q)modn=r]ApBq

我们一般写 DFT 的时候一般会有这样一步操作:

for(;n<sizX+sizY;n<<=1);

也就是说平时的时候我们做 DFT / IDFT 的时候实际上我们是取模了 2v。但是有时候,题目会让我们去做一个 n 次意义下的循环卷积。你说,这很简单,我帮两个多项式乘起来,然后做一个 O(n) 的加法实现循环卷积的功能。听起来很好,但是这个做法有不小隐患,来看一个例题。

IV:P4191

题面

给定两个 n 次多项式 A,B,和一个数字 c,求 A×Bc,其中乘法的定义为 n 次循环卷积。取模 n+1,保证 n+1 是一个质数。

Sol

这时候上面 naive 的做法就不太行了,需要知道一个定理:

两个 n 次多项式的 n 次循环卷积等于他们 DFT 之后系数相乘再进行 IDFT 得到的结果。

这个定理在之前 FFT 的时候,我们是用“点表示法”来理解的。现在我们还可以用单位根反演来证明它,这里就先暂时略过。这个定理的用处在于,如果我们能够求出来 B 的 DFT 形式,对于每一个数做一次快速幂,然后做一次 IDFT 就可以得到 Bcn 次意义下的循环卷积。

回顾我们在做 DFT 的时候要做什么,在 ω0n1 的地方求点值。这时候我们 n 变得一般化了,这意味着要干什么?Bluestein 直接干就对了。

但是这个题目还有一个条件,保证输入的 n 能够分解成若干个不超过 10 的数的乘积。运用这个条件,我们可以换一种方法试一试。

在正常的 FFT 中,我们有两个个关键的式子:

F(ωnk+n/2)=Fe(ωn/2k)ωnkFo(ωn/2k)

F(ωnk)=Fe(ωn/2k)+ωnkFo(ωn/2k)

也就是说,我们通过把多项式分成奇偶两个部分,让两个部分分别只算 n2 个点值,然后如此递归下去,最后只需要做若干个长度为 1 的多项式求一个点值。这样的复杂度就是 O(nlogn)

这个思想是可以推广的,对于一个普通的 n,如果其有因子 d,那么有仍然可以拆分成 d 个多项式求点值的结果,具体地:

A(ωnj)=i=0d1ωnijAi(ωndj)

如果 n 是一个大质数,那么无法这样进行分解,只能做 n 次暴力点值,是非常糟糕的。但是由于 n 最大的质因子为 7,也就是说最后需要暴力做的长度最多是 7,就可以通过这个小技巧不用 Bluestein 的推导同样做出来。

例题

P3746

题面

(i=0(nkik+r))modp

其中 n,k,r,p 给定 r<k50,n109p230

Sol

如果你跟我一样一眼看不出答案就老老实实单位根反演,得到的结果是:

1kj=0k1ωkjr(ωkj+1)nk

同样发现这是一个反演的式子,令 Fr 等于其,那么 (1+ωkj)nk 就是 Fωkj 位置的点值。也就是说 Fi=[xi](1+x)nk 注意这里应该是在 k 次意义下的循环卷积乘法,通过单位根的性质能够得到。需要特判 k=1,因为这时候 (1+x) 本身就超过长度了,应该是 2.

Loj6475

题面

给定 n,s,a0,a1,a2,a3,求:

(i=0n(ni)siaimod4)mod998244353

多测,T105,n1018,s,a108

Sol

显然要拆贡献,得到:

Fv=14avj=03ω4jv(sω4j)n

注意到因为模数是给出来的,则 ω41=gp14 就有 O(16×Tlogn) 的复杂度。

P5591

题面

求:

i=0n(ni)×pi×ikmod998244353

其中 n,p998244353,k106,k=2v

Sol

这题需要一定的转化,向下取整式非常头疼的,向下取整在莫反里面用到的比较多,但这个题和数论函数关系不大。知道 ik=iimodkk,可以开始代换,我试了一下拆贡献,是可以做但是会让题目变得比较复杂,到后面要用白兔之舞的技巧,而且还需要稍微卡常,不拆贡献直接先一起考虑更好,对于后面需要取模的部分再拆贡献(需要用到:m(nm)=n(n1m1)

i=0n(ni)piiimodkk=i=0n(ni)piiki=0n(ni)piimodkk=1k(np(p+1)n1r=0k1r[xr](1+px)n)

后面的部分经典循环卷积,题目很善良地给了 k=2v,因此直接做一次 NTT,然后每一个位置做一个 n 次幂,然后拉回来 ×r 即可。前面的更简单,直接数字运算。

各种 FFT 的套路 + 一些线性代数

FFT 套路

AVL-Tree

转移:

fh[n]=i=0n1fh1[i]×fh1[ni1]+2fh2[i]×fh1[ni1]Fh(x)=x(Fh1(x)2+2Fh1(x)Fh2(x))

ω0ω65535 即可,不用 NTT,最后还原。

Buying snacks

转移:

fi[j]=fi1[j]+fi1[j1]+fi1[j2]+fi2[j1]+fi2[j3]+2fi2[j2]

分情况讨论得到的结果。

Fi(x)=Fi1(x)(1+x+x2)+Fi2(x)(x+x3+2x2)

由于 n 太大,点值不够求 Fn(x) 的系数。

考虑矩阵快速幂:

[Fi(x)Fi1(x)]=[1+x+x2x+2x2+x310][Fi1(x)Fi2(x)]

相当于求 An,中间用多项式乘法。注意优化(减少 DFT / IDFT 的次数)。

复杂度双 log

Poland Ball

转移:

fn,m=fn1,m+fn1,m1+fn2,m1

Fn(x)=(1+x)Fn1(x)+xFn2(x)

矩阵快速幂同样可以双 log

G(z)=i=0nFizi

G(z)=11(1+x)zxz2,之后化成 G(z)=u1Az+v1Bz 的形式。其中 u,v 只和 A,B 相关,A,B 只和 x 相关。

得到 [zn]G(z)=An+1Bn+1AB 全家桶并用,能做到 O(klogk) 因为只用保留 k

Unlucky string(改)

给定 n,m,km 个字符,给定一个长度为 k 的字符串 S。求有多少个长度为 n 的字符串满足其中不含 S 为字串。n,m,k105

fi 表示有多少个长度为 i 且后缀恰好为 s 且前面都没有出现过 s

i<kfi=0,反之则:

fi=mikj=0ikfjmikjdborder(S)fid

d(x)=iborder(S)xi

F(x)=xk1mxxkF(x)1mxF(x)×d(x)

验证起来是比较简单的,要学习正推。

F(x)=xk(1mx)(d(x)+1)+xk

答案为 mni=0nfimni

优化齐次线性递推方程

f 满足:

fi=c1fi1+c2fi2++ckfik

k32000,n109fn

直接用矩阵快速幂大概是 O(k3logn) 的算法,无法满足。

但是还是可以构造出来矩阵:

[fnfnk+1]=[c1c2ck1ck100001000010]×[fn1fnk]

特征多项式

记:

Φ(λ)=λkc1λk1ck

其实就是转移矩阵 M 的特征多项式,关于 M 的特征多项式,定义方式为:

det(λIM)

对于上面式子左侧的结果就是:

det[λc1c2c3ck1λ0001λ0001λ]

用代数余子式计算,能够得到这个行列式算出来就是上面的 Φ(λ)

Cayley - Hamilon 定理

Φ(M)=0

证明是超纲的,有空补。

优化

xn=P(x)×Φ(x)+r(x),即带余除法。则:

Mn=P(M)×Φ(M)+r(M)Mn=r(M)

r(M)=i=0k1riMi

Fi=[fifik+1]

Fn+k1=MnFk1 稍微注意这个最开始矩阵快速幂左边向量的区别。代入有:

Fn+k1=i=0k1riMiFk1=i=0k1riFi+k1

fn=i=0k1rifi

这个是可以 O(k) 算出来的。问题在 r(x) 需要 O(nlogn) 做带余除法,但是注意到 xn 这个形式是简单的,令 a+b=n,有:

xnmodΦ(M)=(xamodΦ(M)×xbmodΦ(M))modΦ(M)

分治下去,可以做到 O(klogklogn)

更多多项式技巧

多项式平移

F(x)=i=0naixi,求 F(x+c)

F(x+c)=i=0nai(x+c)i=i=0naij=0i(ij)xjcij=j=0nxjj!i=jnaii!cij(ij)!

想要求后面的东西

ansi=j=inajj!cji(ji)!=k=0niak+i(k+i)!ckk!=j+k=nianj(nj)!ckk!=j+k=niajckk!

其中 aj=anj(nj)! 再令 ansi=ansni,就有标准形式卷积了。

FFP

FFP 指下降幂多项式。是形如 F(x)=bixi 的多项式。

平移

有下降幂的二项式定理:

(x+y)i=j=0i(ij)xiyij

同理 ansi=j+k=ibjckk!

连续点值 FFP 系数

FFP 是处理连续点值的利器,包括连续点值求和等等。考虑有 f(x)0n 的点值为 y0yn。又知道 f(x)=i=0nbixi 这两者如何转化。

by

yk=f(k)=i=0kbik!(ki)!

ykk!=i=0kbi1(ki)!

yb

y^(x)=y0+y1x1!++ynn!xn

根据上面那个所以综合得到 y^(x)=b(x)exmodxn+1b(x)=exy^(x)modxn+1

如果是给定 cc+n 的时候,通过平移即可。

StirlingNumber

具体内容在这里曾经写过。这里讨论如何快速求一行、一列的 StirlingNumber。

第一类 - 行

转求 xn 的系数,令 fn(x)=xn 注意到 f2n(x)=fn(x)fn(x+n) 通过平移和卷积可以快速做出来。

第二类 - 行

可以用类似的求下降幂系数,还可以用通项公式,即

{nk}=t=0k(1)tt!(kt)n(kt)!

这就是一个简单的标准卷积的形式。

第一类 - 列

[n1]=(n1)! 考虑 EGF 形式,有 n>0xnn!(n1)!=xnn=A^(x)

考虑到斯特林数的意义,可以得到答案就是 1k!A^k(x)

第二类 - 列

同理,有其 EGF 为 ex1,那么答案就是 1k!(ex1)k

Stirling 反演 + snake oil method

Stirling 反演

反演公式

k(1)nk{nk}[km]=[n=m]k(1)nk[nk]{km}=[n=m]

证明不是非常难,代入形式变量 x 之后研究幂次的系数等,这里略。为了方便,可以用矩阵刻画。令 An,k=[nk],An,k=(1)nk[nk]B 同样对于第二类定义。

BA=AB=I

定理

Part I

f(n)=k=0n[nk]g(k)g(n)=k=0n(1)nk{nk}f(k)

证明:把两个函数看作向量,那么 f=Agg=Bf

显然将其中的第一类和第二类斯特林数对换也是成立的。

Part II

f(k)=n=kN[nk]g(n)g(k)=n=kN(1)nk{nk}f(n)

证明:f=ATgg=BTf

其中因为 AB=IATBT=IT=I

例题 TC-13444

给定 nm 列的矩阵,每个位置填 1c 的数,要求:

  1. 任意两行不一样
  2. 任意两列不一样

求方案数 n,m5000,c109

固定行,对于前 m 列,令 g(m) 表示满足第一个限制,f(m) 表示答案。

g(m)=(cm)n 又知道 g(m)=i=0m{mi}f(i) 直接反演:

f(m)=i=0m[mi](1)mig(i)

可以不用多项式算 Stirling。

带权连通图计数问题

n 个点的带标号完全图 Kn,令其所有联通子图的总权值为 Wn。权值定义如下

w(G)=a|E(G)|

  • 法 1:EGF

定义 F^(x)=<W0,W1,Wn>,G^(x)=<g0,g1,gn>,其中 gnEKna|E|

注意到其中

gn=i=0(n2)((n2)i)ai

直觉上告诉我们 G^(x)=exp(F^(x)),因为任意一个图是由若干个连通图构成的。证明:

定义

gn,k=EKn,conn(E)=ka|E|

gn,k=1k!(c1,c2ck)f|c1|f|c2|f|ck|=1k!i1+i2+ik=nn!i1!i2!ik!fi1fi2fik

因此 gn,k 的 EGF 系数为 [xn]1k!F^k(x),又本来的 gn=[xn]gn,k,因此:

G^(x)=k=0+1k!F^k(x)=expF^(x)

Q.E.D.

那么答案 F^(x)=lnG^(x)。特别的,当 a=1 的时候会发现 G^(x)=1+x,则此时 Wn=(1)n1(n1)!。这个可以当作定理记忆。

O(nlogn) 的复杂度


  • 法 2:Stirling 反演

定义对于 n 个点的一个划分 π,定义:f(π) 满足所有的 G 其中每一个划分里面是联通的,但是划分与划分之间是不联通的权值和。g(π) 是所有只需满足划分与划分之间不联通的 G 的权值和。再令:

fk=|π|=kf(π),gk=|π|=kg(π)

观察

gk=ik{ik}fi

证明:考虑每一个 fi 对于 gk,ki 的贡献,相当于把所有联通块放到 k 个盒子里面,系数就是第二类斯特林数。

fk=ikn(1)ik[ik]gk

要求的

f1=i=1n(1)i1(i1)!gk

剩下就在求 g,先看看 a=1 的特殊情况。会发现 gk=1 当且仅当 k=n 其他情况都是 0。因为 kn 的时候,一条边可以被抵消。这样算出来答案同样是 Wn=(1)n1(n1)!

一般的,用 dp 来解决,令 dpn,i 表示 n 个点分成 i 块连边求和的答案。

dpn,i=jn,k(j2)(n1j1)dpnj,i1×ak

经典枚举 1 在哪里。关于 k 可以预处理,因此有一个 O(n3) 的算法。

w(G)=[E(G)=m]

这部分只能用 Stirling 反演。前面的定义都是一样的,现在目标是算出来 gk,直接在 dp 上入手。

dpa,b,c 表示 a 个点 b 个块 c 条边(满足只在块内连边)。

但是看一看这个状态情况,状态就是 O(n4),继续用上面的转移方法,会发现是惊人的 O(n7)。也就是说只能解决 10 个点的情况,非常糟糕。


优化(比较复杂)

这部分是完全 dp。

先写出来:

dpa,b,c=j,k(a1j1)dpaj,b1,ck((j2)k)

“思维不要被限制”

观察

f1=i=1n(1)i1(i1)!gk

考虑后面 (1)i1(i1)!gk 怎么求。

其等价于这样一个问题:

先把所有点分成 B1,Bi 个块,其有序,并且 1 必须在 B1 当中【提供了 (i1)! 的系数】,之后在块里面连接 m 条边【限制条件】,最和这个图的情况贡献是 (1)i1【提供最后一个系数】。

这时候可以定义一个新的 dp。令 dpa,c 表示分成若干个块,块内总边数为 c。这样就成功优化掉了一个维度。

dpa,c(1)×dpat,c(t2)(a1t)

初始 dp[x][(x2)]=1

注意到是块内总边数为 c,最后乘上系数 (cm) 去得到答案。

例题

给定 G1,,Gs 满足都是从 n 个点上的完全图取出来的一个子图。求有多少种选择若干个 G 的方法满足这些图的异或图是联通的。s60,n10.

定义 x 表示一种选择方法,Gx 表示这种选择方法的异或图。定义 f(π) 为有多少个 G(x) 满足划分情况为 π,限制和上面一样。g(π) 同理。其中 fk,gk 和上面一样还是有斯特林反演。

注意到可以枚举 π 其最多就是 Bell(10),然后具体判定就是一个线性基的问题。

不相等计数问题

选择 n 个数,满足 xiSiS 已知。且 x1xn 互不相等。

m=(n2)

考虑构造 m 条边,设 (u,v)=e 之后 Ae 表示选择 xu=xv 这样的满足第一个条件的方案数。

那么答案就是

F{e1em}(1)|F||Ae|

定义一个集合 C{1,n} 定义 h(C) 表示 {Si|iC} 交集的大小。

F{e1em}(1)|F|C:Fh(C)

再次转化,其中注意到 C 只和 π 有关系。

πF,Π(F)=π(1)|F|C:Fh(C)=πCh(C)F,Π(F)=π(1)|F|

最后面一堆相当于是在每一个划分里面都要构造联通图,切贡献是 1 的边数。这就是之前那个定理,因此定义 w(C)=h(C)×(1)|C|1×(|C|1)!

直接用状压 dp,可以做到 O(n3)。但是这里还可以更优,这里

πCw(C)

这个是一个子集卷积的 exp,会在后面再讲。也就可以做到 2n×n2

其实这个题和 Stirling 反演没有什么关系,但是注意到这个容斥过程。在 f,gg 是去掉了 f 块内联通的条件,这个题说明了如果去掉 f 块之间不能连边的条件可以通过容斥反回去。

Snake Oil Method

看到名字的时候觉得莫名其妙的,去查了一下才知道 snake oil 就是万金油的意思。

snake oil method 就是一个对付组合数求和的非常厉害的工具。

That one method is capable of handling a great variety of sums involving binomial coefficients, but there’s nothing special about binomial coefficients in this respect.

看一个例子:

k=0n(knk)

如果先尝试手玩一下可能能发现这就是斐波那契数列。下面来看一下 Snake Oil 怎么解。

先构造出来一个多项式 A(x) 满足 an=k=0n(knk),尝试求其的母函数,展开:

A(x)=n0k=0n(knk)xn=k0xkn0(knk)xnk=k0xkr0k(kr)xr=k0xk(1+x)k=k=0+(x+x2)k=11xx2

会发现得到的结果就是斐波那契的母函数,后面也就不继续下去了。也就是说 A(x) 就是 Fib 的生成函数。

Snake Oil 的基本方法就是放到生成函数中,交换求和顺序,然后尝试解出来里面的东西。有一些比较常见的代换式可以用到:


k(nk)xk=(1+x)n

n(nk)=xk(1+x)k+1

n(2nn)xn=114x

n1n+1(2nn)xn=114x2x


尝试解:

k(n2k)(km)

这个就不好一眼看出来了

nk(n2k)(km)xn=k=0(km)n(n2k)xn=k=0(km)x2k(1x)2k+1=11xk=0(km)[x2(1x)2]k=11x×[x2(1x)2]m[1x2(1x)2]m+1=x2m(12x)m+1×(1x)=(1x)×(x2)m×(2x)m(12x)m+1=(1x)×(x2)mn(nm)(2x)n

这样就是比较方便求出来 xn 的系数了,做两个减法即可。

综合习题、欧拉数、IDFT+

综合习题

数幂求和 I

给定 n,m,求 i[0,m],si=x=0n1xi

方法 0

用斯特林可以得到:

x=0n1j=0i{ij}xj=j=1i{ij}nj+1j+1

这样只有一个 O(n2)

方法 1

S^(x)<s0sm> 的 EGF。

S^(x)=i0j=0n1jixii!=j=0n1ejx=1enx1ex

用多项式求逆,注意的是两个的常数项都是 0。这种时候要都提出一个 x,分母是 i11i!xi=xi01(i+1)!xi。分子是 i0ni+1(i+1)!xi+1=xi0ni+1(i+1)!xi。要求的都是前 m 项,因此复杂度是 O(mlogm)

与伯努利数的关系

1enx1ex=x1ex×1enx1ex

前面的 x1ex 就是伯努利数的系数。

方法 2

让我想到梅加强老师的《数学分析》当中提到的一个技巧——做差。

考虑:

ni+1(n1)n+1=j=0i(i+1j)(n1)j

对于 [1,n] 都做出来这个,之后会不断抵消,最终:

nn+1=j=0i(i+1j)sjni+1(i+1)!=j=0isjj!×1(i+1j)!enx1x=ex1x×S^(x)

幂数求和 II

改一下:six=0n1axi,其中 a 给定。

直接用 EGF 可以得到一个:

j=0n1eajx

但是这个并不好做。

考虑直接用 OGF,能够得到:

S(x)=j=0n111ajx

定义

Q(x)=(1a0x)(1anx)x,P(x)=i=0n1ji(1ajx)

注意到 Q(x) 就是分母,P(x) 就是分子。现在就是要分别求,都可以使用分分治 FFT。具体的,定义 Ql,r,Pl,rQl,r=Ql,mid×Qmid+1,rPl,r=Pl,mid×Qmid+1,r+Pmid+1,r×Ql,mid

这个就是 O(mlog2m)

应用

对于一个多项式 H(x) 系数给定了,求 H(a0x)+H(a1x)+H(an1x)

如果交换求和顺序就有答案:

j=0m1hji=0n1aijxi

这个就是刚才的东西。

例 1

有多少个非负整数 (x1xm)n 个数小于等于 t 并且所有数的和 sS1018,n109,nmn+1000

考虑先枚举出来前面的 n 个数,剩下的限制形如:xn+1+xmS,这是经典组合数。因此答案为:

(S+mnmn)

T=s+mn,z=T(x1+xn)(mn)+1,答案可以写成:

(mn)!zmn=(mn)!k=1mn[mnk]zk

前面都是好求的,关键在于后面的东西,令 s0=T(mn)+1

zk=(s0x1xn)k=k!i0+in=k(s0)i0i0!(xn)inin!

代回:

k!(1)ki0+in=k(s0)i0i0!(x1)i1i1!xninin!

定义 g(i)=0i+ti

k!(1)ki0+in=k(s0)i0i0!g(i0)i0!

定义 G(x)=i0g(i)i!xi,H(x)=i0(s0)ii!xi

因此后面的东西就是 [xk]Gn(x)H(x)

g(i) 可以预处理,只需要一行的斯特林数,无论哪里的复杂度都是 O((mn)log(mn))

P4002

IDFT 的拓展

回顾 Bluestein 我们可以给定系数求点值,而且并不在意长度是多少。观察我们得到的式子

Bm+n=k=0n+mAkCmnk

通过卷积可以求出来 B,然后取后面的若干项就可以得到答案。

不过这个做法是不可逆的。原因是我们把所有的点值是进行平移过的,也就是说单纯给定点值是不知道 B 的前面若干神秘项的。因此无法直接做除法。

点值 系数

已知多项式在 q0qn1 位置的点值,求其系数。

用 Lagrange 差值有:

F(x)=yiji(xqj)ji(qiqj)

这个式子可以改写成,令 A(x)=(xqi)

F(x)=A(x)i=0n1yiA(qi)×(xqi)

只需要证明 A(qi)=(qiqj) 这个是比较显然的。

问题分成三步:

1. 求 A(x)

分治 FFT,有显然的 O(nlog2n),不过因为是等比的,所以分治的时候右边多项式可以从左边推出来,因此复杂度可以少一个 log

2. 求 di=yiA(qi)

A(x) 是好求的,剩下的就是等比求点值用 Bluestein 可以解决。

3. 求 i=0n1dixqi

1xqi 拆开,然后交换求和顺序,能够有:

j=0ni=0n1diqi(j+1)xj

如果定义一个多项式 D(x) 那么后面又是一个等比求值的问题,还是可以 Bluestein。

因此总复杂度是 O(nlogn) 前提是给定的是等比的。

浅看了一个随机点值,那个也是可以做的,需要知道非等比求点值(Bluestein 无法使用),然后思路基本一样,复杂度是 O(nlog2n)

欧拉数

nk 表示长度为 n 的排列恰好有 k 次上升的方案数。

有比较显然的递推:

nk=(k+1)n1k+(nk)n1k1

考虑如何快速单点求值和求一行。

下面默认求第 n 行,令 fk 表示答案,令 gk 表示钦定了 k 个位置是上升的。

gk=i=kn(ik)fi

有一个比较巧妙的观察:gk=(nk)!{nnk}。可以分析连续上升段,每一段相当于一个盒子。

因此:

fk=i=kn(1)ik(ik)(ni)!{nni}

用斯特林的通项公式展开,并且做一些替换:

fk=i=0nk(1)nik(nik)t=0i(1)it(it)tn=t=0nk(1)nkttni=tnk(nik)(it)=(1)nkt=0nktn(1)t(n+1k+t+1)

最后一步考虑组合意义。相当于 n+1 个球先选择一个求作为分界点,剩下的左边选择 k 个右变选择 t 个。

这个公式可以快速算出来单点。其中 tn 是积性函数可以线性算。

注意到:

nk=nnk

如果把这个带进去,能够有:

fk=t=0k+1(k+1t)n(1)t(n+1t)

这个是可以 FFT 的。

posted @   Jryno1  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示