Typesetting math: 38%

数学小结(持续更新)

数学小结

前言:这篇文章专门整理了各种有关数学的东西(包括原理和例题),主要是怕自己忘了。

整理的不齐全,而且写的都是比较基础的东西。

UPD:把代码和例题全删了。

扩展欧几里得(exgcd)

问方程 ax+by=cax+by=cxx 的最小非负整数解。

根据贝祖定理,若 gcd(a,b)|cgcd(a,b)|c,则方程有解,否则无解。

那么我们先可以求出 ax+by=gcd(a,b)ax+by=gcd(a,b) 的一组解,然后 xxyy 同时乘上 cgcd(a,b)cgcd(a,b),就可以得到 ax+by=cax+by=c 的解了。至于怎么求 xx 的最小非负整数解,我们先要将原方程约分,即 aabbcc 都除以 gcd(a,b)gcd(a,b),然后再根据不定方程,让 xx 模上 bb 就好了。

现在的问题就是如何求出 ax+by=gcd(a,b)ax+by=gcd(a,b) 的一组解。

考虑用类似求 gcdgcd 的辗转相除法求解。

假设我们已经求出了 ax+by=gcd(a,b)ax+by=gcd(a,b) 的一组解,其中 a=ba=bb=amodb=aab×bb=amodb=aab×b,现在考虑如何求 xxyy 的一组解。

显然,根据辗转相除法,gcd(a,b)=gcd(b,amodb)=gcd(a,b)gcd(a,b)=gcd(b,amodb)=gcd(a,b)

那么有:

ax+by=gcd(a,b)bx+(aab×b)y=gcd(a,b)ay+b(xab×y)=gcd(a,b)ax+by=gcd(a,b)bx+(aab×b)y=gcd(a,b)ay+b(xab×y)=gcd(a,b)

可以推得:

{x=yy=xab×y{x=yy=xab×y

这样就可以求出 xxyy 的一组解了。

考虑边界情况:当 b=0b=0 时,有 ax=gcd(a,b)=aax=gcd(a,b)=a,得 x=1x=1y=0y=0

然后根据一开始说的方法就能求出 xx 的最小非负整数解了。

求逆元

a×x1(modp)a×x1(modp),则称 xxaa 在模 pp 意义下的逆元,记作 a1a1,通常来算 1amodp1amodp 的值。(保证 gcd(a,p)=1gcd(a,p)=1

  1. pprimepprime,根据费马小定理,ap11(modp)ap11(modp),即 a×ap21(modp)a×ap21(modp),那么答案即为 ap2modpap2modp

  2. pprimepprime,那么 a×x1(modp)a×x1(modp) 可以看做是 ax+py=1ax+py=1 的一组解。

中国剩余定理(crt)

问以下方程的最小非负整数解:

{xa1(modp1)xa2(modp2)xak(modpk)⎪ ⎪ ⎪⎪ ⎪ ⎪xa1(modp1)xa2(modp2)xak(modpk)

其中 p1,p2,,pkp1,p2,,pk 为两两互质的数。

而这个定理貌似就是在构造一个特殊解。

M=ki=1piM=ki=1pimi=Mpimi=Mpititimimi 在模 pipi 意义下的逆元,则有 mi×ti1(modpi)mi×ti1(modpi)

那么这个方程的一个特殊解就是:x0=ki=1aimitix0=ki=1aimiti

证明:

对于任意的 ii,我们考虑 x0ai(modpi)x0ai(modpi) 是否成立。

x0x0 拆解成两部分之和:x0=kj=1,jiajmjtj+aimitix0=kj=1,jiajmjtj+aimiti

显然,对于任意的 jijiajmjtjmodpiajmjtjmodpi 肯定为 00,因为 mjmj 的定义就是除了 pjpj 之外的 pipi 之积,得 mjmodpimjmodpi00

那么就可以得到 kj=1,jiajmjtj0(modpi)kj=1,jiajmjtj0(modpi)

然后因为 miti1(modpi)miti1(modpi),得 aimitiai(modpi)aimitiai(modpi)

所以 x0=kj=1,jiajmjtj+aimitiai(modpi)x0=kj=1,jiajmjtj+aimitiai(modpi)

那么 x0x0 就是 xx 的一个特殊解了。

证毕。

然后又因为 xx 一定是 aM+baM+b 的形式,所以 xmin=x0modMxmin=x0modM

扩展中国剩余定理(excrt)

问以下方程的最小非负整数解:

{xa1(modp1)xa2(modp2)xak(modpk)⎪ ⎪ ⎪⎪ ⎪ ⎪xa1(modp1)xa2(modp2)xak(modpk)

发现这类问题和普通中国剩余定理的区别就是少了这个条件:“其中 p1,p2,,pkp1,p2,,pk 为两两互质的数”。

这就导致了 mimi 在模 pipi 意义下的逆元可能根本不存在,所以不能那么做。

假设前 ii 个方程组的特殊解已经求出来为 x0x0

Mi=lcmij=1pjMi=lcmij=1pj

那么前 ii 个方程组的通解为 xi=x0+Mi×txi=x0+Mi×ttZtZ)。

我们现在就是要找到一个 tt,使得 x0+Mi×tai(modpi)x0+Mi×tai(modpi),即 Mi×taix0(modpi)Mi×taix0(modpi)

这个用 exgcd 来做就可以了。

然后这么一直下去就能得到最后的解了。

卢卡斯定理(Lucas)

(nm)modp(nm)modp 的值,其中 pprimepprime

n=ap+bn=ap+bm=lp+rm=lp+r

那么 (nm)(nm) 就相当于 (x+1)n(x+1)n 的展开式中 xmxm 的系数。

然后先证明一个东西:(x+1)pxp+1(modp)(x+1)pxp+1(modp)

证明比较简单,把 (x+1)p(x+1)p 展开,得 (x+1)ppi=0(pi)xi(modp)(x+1)ppi=0(pi)xi(modp),其中对于任意的 0<i<p0<i<p,肯定有 (pi)=p×(p1)××(pi+1)1×2××i(pi)=p×(p1)××(pi+1)1×2××ipp 的倍数,因为 pp 为质数,1i1i 均与 pp 互质。

证毕。

然后推式子:

(x+1)n(x+1)ap+b(x+1)ap×(x+1)b((x+1)p)a×(x+1)b(xp+1)a×(x+1)b(ai=1(ai)xip)×(bj=1(bj)xj)(modp)(x+1)n(x+1)ap+b(x+1)ap×(x+1)b((x+1)p)a×(x+1)b(xp+1)a×(x+1)b(ai=1(ai)xip)×(bj=1(bj)xj)(modp)

然后考虑如何找到这个式子中的第 mm 次项。

m=lp+rm=lp+r

由于 1jbp1jbp,所以 xm=xlp+rxm=xlp+r 只能是由第一个括号里面的 xlpxlp 和第二个括号里面的 xrxr 拼凑而来,故 xmxm 的系数为 (al)×(br)(al)×(br)

又因为 xmxm 本来的系数就是 (nm)(nm),所以得:

(nm)=(al)×(br)=(npmp)×(nmodpmmodp)(nm)=(al)×(br)=(npmp)×(nmodpmmodp)

然后就可以递归求解了。

一个进阶结论:f(x)pf(xp)modpf(x)pf(xp)modp,其中 pp 为质数。

证明:考虑从每个 f(x)f(x) 中选取的幂次的可重集 SS 确定后,分配幂次的方案数。设共出现了 kk 种幂次且它们分别出现了 a1,,aka1,,ak 次,那么方案数为 (pa1,,ak)(pa1,,ak)。容易发现当 k>1k>1 时这个组合数的值模 pp 一定是 00,所以现在只需要考虑 k=1k=1 即每个 f(x)f(x) 选取的幂次都相同的情况。

不妨设选择了都选的是 ii 幂次,ii 幂次的系数为 cc,那么乘起来后贡献到 pipi 幂次,贡献的值为 cpcp,根据欧拉定理,有 cpc(modp)cpc(modp),从而得到的就是 f(xp)f(xp)

扩展卢卡斯定理(exLucas)

求:

(nm)modp(nm)modp

其中 n,m1018n,m1018p106p106不保证 pp 为质数

先将 pp 分解质因数:p=pk11pk22pkmmp=pk11pk22pkmm,然后求出 (nm)modpkii(nm)modpkii,最后用中国剩余定理合并即可。


(nm)modpk(nm)modpk

用阶乘拆出来:n!m!(nm)!modpkn!m!(nm)!modpk,注意不能直接求 m!m!(nm)!(nm)! 的逆元,因为不保证它们和 pkpk 互质。

g(n)g(n)n!n! 中包含的 pp 的次数,f(n)f(n) 为将 n!n! 除尽 pp 后得到的结果(满足 f(n)=n!pg(n)f(n)=n!pg(n))。

转化为求:f(n)f(m)f(nm)×pg(n)g(m)g(nm)modpkf(n)f(m)f(nm)×pg(n)g(m)g(nm)modpk,其中 f(n),f(m),f(nm)f(n),f(m),f(nm) 均与 pkpk 互质,存在逆元(可以根据扩展欧拉定理 gcd(a,m)=1aφ(m)1(modm)gcd(a,m)=1aφ(m)1(modm) 求,或使用 exgcd),于是求出 ffpkpk 的结果和 gg 即可。

g(n)g(n) 比较简单,不讲了,时间复杂度 O(logpn)O(logpn)


f(n)modpkf(n)modpk

n!n! 进行变形:

n!=1×2××n=(p×2p×)(1×2×)n!=1×2××n=(p×2p×)(1×2×)

其中左边括号内为所有 pp 的倍数,右边括号内为所有与 pp 互质的数(当然也与 pkpk 互质)。

提出 pp 来:

n!=(p×2p×)(1×2×)=pnp(np)!(1×2×)n!=(p×2p×)(1×2×)=pnp(np)!(1×2×)

那么根据 f(n)f(n) 的定义:

f(n)f(np)(1×2×)(modpk)f(n)f(np)(1×2×)(modpk)

现在问题是求出 (1×2×)modpk(1×2×)modpk,为 nn 中所有与 pp 互质的数的乘积。

求出来之后就可以递归求 ff 了,边界条件 f(0)=1f(0)=1


(ni=1,p|ii)modpk(ni=1,p/|ii)modpk

法一:

根据 xx+pk(modpk)xx+pk(modpk) 可知有长度为 pkpk 的循环节,于是等于:

(pki=1,p|ii)npk(ni=pknpk+1,p|ii)=(pki=1,p|ii)npk(nmodpki=1,p|ii)pki=1,p/|iinpk⎜ ⎜ni=pknpk+1,p/|ii⎟ ⎟=pki=1,p/|iinpknmodpki=1,p/|ii

那么可以先 O(pk)O(pk) 预处理,每次 O(1)O(1) 求解。

法二:

上述方法的瓶颈在求 nn 中所有与 pp 互质的数的乘积需要 O(pk)O(pk) 预处理,这里有另一种适用于 ppkk 大做法:

hn(x)=ni=1,p|i(x+i)hn(x)=ni=1,p/|i(x+i),我们要求的就是 [x0]hn(x)[x0]hn(x)

可以使用倍增求解:

p=npp=nppp 的倍数,那么 h2p(x)=hp(x)hp(x+p)h2p(x)=hp(x)hp(x+p)

考虑归纳证明:假设我们想要知道 [xi]h2p(x)modpki[xi]h2p(x)modpki0ik0ik),那么我们只需要知道 [xi]hp(x)modpki[xi]hp(x)modpki0ik0ik)。

首先有一个容易证明的引理:对于 A(x)=B(x)C(x)A(x)=B(x)C(x),假设我们想要知道 [xi]A(x)modpki[xi]A(x)modpki0ik0ik),那么我们只需要知道 [xi]B(x)modpki[xi]B(x)modpki[xi]C(x)modpki[xi]C(x)modpki0ik0ik)。

根据引理,现在只需要证明知道了 [xi]hp(x)modpki[xi]hp(x)modpki 是否就能知道 [xi]hp(x+p)modpki[xi]hp(x+p)modpki

ai=[xi]hp(x)=qipki+riai=[xi]hp(x)=qipki+ri

 [xi]hp(x+p)=kj=i[xi]aj(x+p)j=kj=i(ji)ajpji=kj=i(ji)qjpkinji+(ji)rjpjikj=i(ji)rjpji(modpki) [xi]hp(x+p)=kj=i[xi]aj(x+p)j=kj=i(ji)ajpji=kj=i(ji)qjpkinji+(ji)rjpjikj=i(ji)rjpji(modpki)

于是要求 [xi]hp(x+p)modpki[xi]hp(x+p)modpki 只需 rjrj,即 [xj]hp(x)modpkj[xj]hp(x)modpkj,证毕。

而对于求 h2p+q(x)=h2p(x)2p+qi=2p+1,p|i(x+i)h2p+q(x)=h2p(x)2p+qi=2p+1,p/|i(x+i)q<2pq<2p)的情况,根据上面提到的引理,我们只需要求出 h2p(x)h2p(x) 每一位模 pkipki 的多项式,然后暴力乘上后面那部分即可。

具体实现上为了简便,我们可以保留前 k1k1 项然后全部对 pkpk 取模,而不是对 pkipki 取模。

注意这里求 hp(x+p)hp(x+p) 时需要用到组合数 (ji)(ji),这个不能拆成阶乘(因为同样可能不存在逆元),但可以杨辉三角 O(k2)O(k2) 预处理。

时间复杂度 O((pk+k2)logpn)O((pk+k2)logpn)


如果使用第一种方法:

总时间复杂度 O(pk)O(logpkn)O(pk)O(logpkn),当 pp 为质数时取到上界 O(p)O(logpn)O(p)O(logpn)

特别地,由于我们使用了预处理优化,对于同一个 pp 多组询问的复杂度为 O(pk)O(Tlogpkn)O(pk)O(Tlogpkn)

如果使用第二种方法:

总时间复杂度 O((pk+k2)log2pn)O((pk+k2)log2pn)

Baby Step Giant Step(BSGS,北上广深

axb(modp)axb(modp) 的最小非负整数解,其中 pprimepprime

t=pt=px=itjx=itj。(因为 pprimepprime,所以 0xp10xp1

axb(modp)aitjb(modp)aitb×aj(modp)axb(modp)aitjb(modp)aitb×aj(modp)

然后我们先可以 O(p)O(p)b×ajb×aj 的所有值存进 hash 表里面。

然后我们再 O(p)O(p) 枚举 ii,在 hash 表里面找是否有 aitb×aj(modp)aitb×aj(modp)

exBSGS

求满足 axb(modp)axb(modp) 的最小自然数 xx,不保证 a,pa,p 互质。

根据循环节仍可以粗略地看出 xx 的范围仍在 [0,p)[0,p) 内。

考虑 a,pa,p 互质时,我们是将 xx 表示成 cBdcBd,然后变成 acBbad(modp)acBbad(modp),但这其实利用到了 aa 在模 pp 意义下有逆元即 a,pa,p 互质的性质,因为 axay(modp)axay(modp)a,pa,p 不互质时并不蕴含 axy1(modp)axy1(modp)

g=gcd(a,p)g=gcd(a,p)

  • g=1g=1,直接 BSGS。

  • b=1b=1,则 x=0x=0

  • b1b1,则 x1x1。那么若 gbgb 必然无解,否则可以递归到计算 agax1bg(modpg)agax1bg(modpg)xx 的最小正整数解,即 axbg(ag)1(modpg)axbg(ag)1(modpg)xx 的最小非负整数解。

事实上可以避免求逆,可以把问题描述成 caxb(modp)caxb(modp) 的形式,其中 c,pc,p 互质,这样每次就给 cc 多乘上一个数,最后对这个问题类似地做 BSGS 即可。

矩阵树定理

对于一个大小为 n2n2 的矩阵 AA,定义其行列式 det(A)det(A) 为:(det(A)det(A) 也作 |A||A|

det(A)=P(1)μ(P)ni=1A(i,pi)det(A)=P(1)μ(P)ni=1A(i,pi)

其中 PP1n1n 的一个排列,μ(P)μ(P) 是排列 PP 的逆序对数。

也就是说,我们在矩阵的每一行选一个数(它们所在的列互不相同),然后乘起来。对于每一种选数方案,赋予它一个与逆序对有关的系数,再加起来。

矩阵树定理有以下的性质:

  1. 交换矩阵的两行,行列式变号。

    也就等同于交换一个 1n1n 排列的两个数,整个序列改变的逆序对数为奇数。

    证明:

    设交换的这两个数位置是在 iijj 位置,分别是 xxyy

    我们把序列分成三段,AA 段为 1(i1)1(i1)BB 段为 (i+1)(j1)(i+1)(j1)CC 段为 (j+1)n(j+1)n。(如图)

    显然,交换 xxyy 后,xxAACC 两段的相对位置没有改变,yyAACC 两段的相对位置也没有改变,所以由 (A,x)(A,x)(A,y)(A,y)(x,C)(x,C)(y,C)(y,C) 贡献的逆序对数没有改变。

    那么我们只需要考虑 (x,B)(x,B)(B,y)(B,y) 两种情况改变的逆序对数就好了。

    BB 段中一共有 SS 个数,其中比 xx 小的数有 aa 个,比 yy 大的数有 bb 个,那么这段中比 xx 大的数有 SaSa 个,比 yy 小的有 SbSb 个。

    可以知道交换前,这两种情况贡献的逆序对数共有 a+ba+b 个。

    交换后,这两种情况贡献的逆序对数共有 (Sa)+(Sb)=2S(a+b)(Sa)+(Sb)=2S(a+b) 个。

    前后贡献的逆序对数之差为 [2S(a+b)](a+b)=2(Sab)[2S(a+b)](a+b)=2(Sab),为偶数。

    所以 (x,B)(x,B)(B,y)(B,y) 两种情况改变的逆序对数为偶数对。

    注意到 xxyy 交换后,(i,j)(i,j) 可能从一开始不是逆序对变成了逆序对,也可能从一开始是逆序对变成了不是逆序对,变动对数为奇数。

    所以总的变动对数为奇数对。

    证毕。

  2. 矩阵的某一行乘上 kk,行列式也乘上 kk

  3. |a+ab+bcd|=|abcd|+|abcd|a+ab+bcd=abcd+abcd

  4. 若矩阵中某两行相同,则它的行列式为 00

  5. 用矩阵的一行加上另一行的倍数,行列式不变。

其中上面的第 2424 点的证明在这篇题解有详细阐述,不会的可以直接去看。

发现第 55 点操作很像高斯消元中的操作,所以可以考虑用类似高斯消元的方法把行列式变成一个右上三角矩阵,然后这个矩阵的行列式就是对角线上的乘积。

以上是关于行列式和如何求行列式(O(n3)O(n3))。

接下来是矩阵树定理:

  1. 无向图。设 AA 为邻接矩阵,DD 为度数矩阵(D(i,i)D(i,i) 为节点 ii 的度数,其他的无值)。则基尔霍夫 (Kirchhoff)矩阵即为 : K=DAK=DA。把 KK 去掉任意第 ii 行和第 ii 列后的矩阵 KK 的行列式即为答案。

  2. 有根扩展。设根为 rtrt,则把 KK 去掉第 rtrt 行和第 rtrt 列后的矩阵 KK 的行列式即为答案。

  3. 有向扩展。若为外向树,则度数矩阵统计的是入度;若为内向树,则度数矩阵统计的是出度。

  4. 边权扩展。假设有一条边 (u,v,w)(u,v,w),那么可以看成是在 (u,v)(u,v) 之间,一共有 ww 条重边。

    那么我们把度数变成边权就好了。

    此时矩阵树定理求的就是 : 所有生成树边权乘积的总和。

LGV 引理

G=(V,E)G=(V,E) 是 DAG,边有边权。

PPGG 中的一条路径,定义其权值 w(P)w(P)PP 上所有边的边权积。

{A1,,An},{B1,,Bn}{A1,,An},{B1,,Bn}GG 的两个大小相同的子集。

定义 ABAB 的一组路径为 S=(S1,,Sn)S=(S1,,Sn),使得存在 1,,n1,,n 的排列 p(S)p(S),满足 SiSiAiAiBp(S)iBp(S)i 的一条路径。

ABAB 的一组路径 SS 是不相交的,当且仅当对于任意 ijij 都有 SiSiSjSj 无交。

LGV 引理:

n×nn×n 的矩阵 MM 满足

M(i,j)=P:AiBjw(P)M(i,j)=P:AiBjw(P)

那么:

det(M)=S:ABS不相交(1)σ(p(S))ni=1w(Si)det(M)=S:ABS(1)σ(p(S))ni=1w(Si)

证明:

考虑 det(M)det(M),事实上为:

S:AB(1)σ(p(S))ni=1w(Si)S:AB(1)σ(p(S))ni=1w(Si)

为证明 LGV 引理,设 UUABAB 的所有相交路径组 SS 组成的集合,我们考虑构造 UU 中的双射 ff,使得双射的两组路径 S,TS,T 满足 (1)σ(p(S))ni=1w(Si)(1)σ(p(S))ni=1w(Si)(1)σ(p(T))ni=1w(Ti)(1)σ(p(T))ni=1w(Ti) 互为相反数。

设任意 SUSU。设 ppVV 中最小的元素,使得存在 ijij 使得 Si,SjSi,Sjpp 处有交。假设经过 pp 的路径的编号集合为 KK,找到 KK 中最小的两个元素 i,ji,j,然后交换 Si,SjSi,Sjpp 之后的部分,得到 SS 并将它作为 f(S)f(S)。容易观察到,p(S)p(S) 恰是 p(S)p(S) 交换两个元素后的结果,所以它们的逆序对数奇偶性不同,所以能相互抵消。同时也容易证明 f(S)=Sf(S)=S

积性函数

积性函数:对于一个函数 f(x)f(x),若有 f(ab)=f(a)f(b)f(ab)=f(a)f(b),其中 gcd(a,b)=1gcd(a,b)=1,则称 f(x)f(x) 为积性函数。

完全积性函数:对于一个函数 f(x)f(x),若有 f(ab)=f(a)f(b)f(ab)=f(a)f(b),则称 f(x)f(x) 为完全积性函数。

常见的积性函数及其求法:

  1. 欧拉函数(φφ

    定义:φ(n)φ(n) 是小于或等于 nn 的正整数中与 nn 互质的数的个数。

    求法:

    首先对于 pprimepprime,肯定有 φ(p)=p1φ(p)=p1

    然后对于 pprimepprime,有 φ(pk)=pkpk1φ(pk)=pkpk1,因为除了 pp 的倍数以外的其他数都与 pkpk 互质。

    再加上它是个积性函数,就可以用线性筛求 φφ 了。

    单点求 φφ

    φ(n)φ(n),设 n=pk11pk22pkmmn=pk11pk22pkmm,则:

    φ(n)=φ(pk11)φ(pk22)φ(pkmm)=pk111(p11)×pk212(p21)××pkm1m(pm1)=np1p2pm×(p11)(p21)(pm1)=n(p11p1)(p21p2)(pm1pm)φ(n)=φ(pk11)φ(pk22)φ(pkmm)=pk111(p11)×pk212(p21)××pkm1m(pm1)=np1p2pm×(p11)(p21)(pm1)=n(p11p1)(p21p2)(pm1pm)

    于是就可以 O(n)O(n)φ(n)φ(n) 了。

  2. 莫比乌斯函数(μμ

    μ(n)={1n=1(1)kn 无大于 1 的平方数因数,n 分解质因数为 n=p1p2pk0n 有大于 1 的平方数因数μ(n)=1n=1(1)kn  1 n  n=p1p2pk0n  1 

    根据这个定义,我们就可以线性筛了。

常见的完全积性函数:

  1. ϵ(n)=[n=1]ϵ(n)=[n=1]
  2. I(n)=1I(n)=1
  3. id(n)=nid(n)=n

这里记一些可能有用的式子:

  • d(ij)=x|iy|j[gcd(x,y)=1]d(ij)=x|iy|j[gcd(x,y)=1]

    证明:对于每个质数幂分别考虑。对于质数 pp,假设 iipp 的幂次为 aajjpp 的幂次为 bb。那么左右两式都被统计了 a+b+1a+b+1 次。

狄利克雷卷积

f,gf,g 是两个数论函数,定义他们的狄利克雷卷积是:(fg)(n)=d|nf(d)g(nd)(fg)(n)=d|nf(d)g(nd)。(以下若无特殊说明均用 表示狄利克雷卷积)

和普通卷积 ci+j=aibjci+j=aibj 不同,这里是 ci×j=aibjci×j=aibj

注意狄利克雷卷积针对的是数论函数,而不只是积性函数。

重要的性质:

  • f,gf,g 是积性函数,那么 fgfg 也是积性函数。

    证明:(其中 gcd(p,q)=1gcd(p,q)=1

    (fg)(pq)=d|pqf(d)g(pqd)=d1|pd2|qf(d1d2)g(pqd1d2)=d1|pf(d1)g(pd1)d2|qf(d2)g(qd2)=(fg)(p)×(fg)(q)(fg)(pq)=d|pqf(d)g(pqd)=d1|pd2|qf(d1d2)g(pqd1d2)=d1|pf(d1)g(pd1)d2|qf(d2)g(qd2)=(fg)(p)×(fg)(q)

    其中第一步跳到第二步是因为 p,qp,q 互质,第二步跳到第三步是因为 d1,d2d1,d2 互质且 pd1,qd2pd1,qd2 互质。

  • f,gf,g 是完全积性函数,那么 fgfg 也是完全积性函数。

  • ff 是积性函数,那么 f1f1 也是积性函数。

  • ff 是完全积性函数,那么 f1f1 也是完全积性函数。

它满足交换律、结合律。

然后对于任意的 ff,有 fϵ=ffϵ=f

常见的狄利克雷卷积有:

  1. μI=ϵμI=ϵ,即 d|nμ(d)=[n=1]d|nμ(d)=[n=1]

    证明:

    n=1n=1,则易得原式等于 11

    n1n1,将 nn 质因数分解得 n=pa11pa22pammn=pa11pa22pamm

    设枚举到的 d=px11px22pxmmd=px11px22pxmm

    按枚举到的 dd 分类讨论:

    1. 对于所有的 xixi,存在有至少一个 xi>1xi>1

      此时 μ(d)=0μ(d)=0

    2. 对于所有的 xixi,都有 xi1xi1

      那么这部分的 ansans 为:

      ans=mi=0(mi)(1)ians=mi=0(mi)(1)i

      其中第一个 mi=0mi=0 枚举所有的 xjxj 中(1jm1jm),有 iixjxj 大于 00,即有 iixjxj11

      然后 (mi)(mi) 意思是从所有的 xjxj 中(1jm1jm),选出 iixjxj11 的方案数。

      然后 (1)i(1)i 就是 μ(d)μ(d)

      至于 ansans 为什么等于 00

      1. m1(mod2)m1(mod2)

        +(m0)+(m0) 会和 (mm)(mm) 抵消,(m1)(m1) 会和 +(mm1)+(mm1) 抵消……以此类推,可得 ans=0ans=0

      2. m0(mod2)m0(mod2)

        将每个 (mi)(mi) 都画在杨辉三角里:

        ans=(m0)(m1)+(m2)(mm1)+(mm)=(m10)[(m10)+(m11)]+[(m11)+(m12)][(m1m2)+(m1m1)]+(m1m1)=0ans=(m0)(m1)+(m2)(mm1)+(mm)=(m10)[(m10)+(m11)]+[(m11)+(m12)][(m1m2)+(m1m1)]+(m1m1)=0

      所以无论如何,都有 ans=0ans=0

      所以当 n1n1 时,原式为 00

      证毕。

  2. φI=idφI=id,即 d|nφ(d)=nd|nφ(d)=n

    证明:

    首先把式子转换一下:d|nφ(d)=d|nφ(nd)d|nφ(d)=d|nφ(nd)

    考虑每一个 φ(nd)φ(nd) 代表着什么。

    可以把 φ(nd)φ(nd) 看成小于等于 nn 的所有正整数中,与 nngcdgcddd 的个数。

    那么 d|nφ(nd)d|nφ(nd) 就可以看成所有小于等于 nn 的正整数个数,得 d|nφ(nd)=nd|nφ(nd)=n

    证毕。

  3. μid=φμid=φ,即 d|nμ(d)×d=φ(n)d|nμ(d)×d=φ(n)

    证明:

    首先由(2)得 φI=idφI=id

    φIμ=idμφIμ=idμ

    φϵ=idμφϵ=idμ

    φ=idμφ=idμ

    证毕。

贝尔级数

定义数论函数 ff 在质数 pp 上的贝尔级数 fp(x)fp(x)

fp(x)=i0f(pi)xifp(x)=i0f(pi)xi

那么有:

(fg)p(x)=fp(x)gp(x)(fg)p(x)=fp(x)gp(x)

证明:

(fg)p(x)=i0(fg)(pi)xi=i0xid|pif(d)g(pid)=i0ij=0f(pj)xjg(pij)xij=fp(x)gp(x)(fg)p(x)=i0(fg)(pi)xi=i0xid|pif(d)g(pid)=i0ij=0f(pj)xjg(pij)xij=fp(x)gp(x)

同时,若 fp(x)gp(x)=hp(x)fp(x)gp(x)=hp(x)hh 为积性函数,那么 h=fgh=fg

这样就能用普通的卷积来刻画狄利克雷卷积。

因为狄利克雷卷积 (fg)(n)(fg)(n) 的实际上是在枚举两个数 a,ba,b 使得 ab=nab=n,那么相当于对于 nn 的每一个质因子及其幂 pkpk 枚举 i+j=ki+j=k,那就由狄利克雷卷积变成了普通卷积。

对于完全积性函数 ff 有:

fp(x)=i0f(pi)xi=i0fi(p)xi=11f(p)xfp(x)=i0f(pi)xi=i0fi(p)xi=11f(p)x

常见数论函数的贝尔级数:

  • ϵp(x)=1ϵp(x)=1。(ϵ(n)=[n=1]ϵ(n)=[n=1]
  • 1p(x)=11x1p(x)=11x。(1(n)=11(n)=1
  • idp(x)=11pxidp(x)=11pxidkp(x)=11pkxidkp(x)=11pkx。(id(n)=nid(n)=nidk(n)=nkidk(n)=nk
  • μp(x)=1xμp(x)=1xμ2p(x)=1+xμ2p(x)=1+x
  • φp(x)=1x1pxφp(x)=1x1px

于是你可以看出这些数论函数之间的很多关系,如:

  • μp(x)×1p(x)=ϵp(x)μp(x)×1p(x)=ϵp(x),那么 μ1=ϵμ1=ϵ
  • μp(x)×idp(x)=φp(x)μp(x)×idp(x)=φp(x),那么 μid=φμid=φ
  • φp(x)×1p(x)=idp(x)φp(x)×1p(x)=idp(x),那么 φ1=idφ1=id

通过贝尔级数也可以更加容易地看出一些奇怪的数论函数与常见的数论函数的关系,这对杜教筛的构造有很大的作用。

莫比乌斯反演

定理:若 g=fIg=fI,即 g(n)=d|nf(d)g(n)=d|nf(d),则 f=gμf=gμ,即 f(n)=d|ng(d)μ(nd)f(n)=d|ng(d)μ(nd)

证明: g=fIg=fIgμ=fIμ=fϵ=fgμ=fIμ=fϵ=f,证毕。

杜教筛

求一个积性函数 ff 的前缀和,记 S(n)=ni=1f(i)S(n)=ni=1f(i)

再找一个积性函数 gg,先考虑它们的狄利克雷卷积的前缀和:

ni=1(fg)(i)=ni=1d|if(d)g(id)=nd=1g(d)ndi=1f(i)=nd=1g(d)S(nd)ni=1(fg)(i)=ni=1d|if(d)g(id)=nd=1g(d)ndi=1f(i)=nd=1g(d)S(nd)

考虑 g(1)S(n)g(1)S(n) 是什么,发现:

g(1)S(n)=nd=1g(d)S(nd)nd=2g(d)S(nd)=ni=1(fg)(i)nd=2g(d)S(nd)g(1)S(n)=nd=1g(d)S(nd)nd=2g(d)S(nd)=ni=1(fg)(i)nd=2g(d)S(nd)

那么我们就可以找到或构造一个 gg,使得 ni=1(fg)(i)ni=1(fg)(i)gg 的前缀和可以快速算,然后数论分块递归求解。

然后可以预处理出前若干个答案的前缀和,并且加上记忆化,可以把时间复杂度优化成 O(n23)O(n23),其中要处理前 n23n23 个答案的前缀和。

min_25 筛

记号:

  • 记质数集合为 PP

  • 如无特殊说明,以下记为 pp 的变量的取值集合为质数集合。

  • pkpk 指第 kk 个质数。

  • lpf(n)lpf(n) 表示 nn 的最小质因数。

  • 为了方便,有时用 (a/b)(a/b) 表示 abab

  • 特别地,p0=1p0=1lpf(1)=1lpf(1)=1,那么就保证了不存在 ii 使得 lpf(1)>pilpf(1)>pi

min_25 筛用来解决这样一类问题:问 f(x)f(x) 前缀和 ni=1f(i)ni=1f(i)。其中 f(x)f(x) 需要满足以下条件:

  • f(x)f(x) 为积性函数;
  • f(p)f(p) 为低次多项式;
  • f(pe)f(pe) 可以快速求值。

具体为什么要满足这些条件在下面有体现。

我们将 i=1ni=1n 分为质数和合数两类讨论:

ni=1f(i)=f(1)+pnf(p)+pn,penf(pe)(2i(n/pe),lpf(i)>pf(i)+[e>1])ni=1f(i)=f(1)+pnf(p)+pn,penf(pe)2i(n/pe),lpf(i)>pf(i)+[e>1]

注意若 x 为合数,那么 x 的最小质因数 px,所以我们 p 只需枚举到 n 即可。

S(n,i)=nx=1[lpf(x)>pi]f(x),那么就可以递推:

S(n,i)=pnf(p)ppif(p)+k>i,pkn,peknf(pek)(S(npek,k)+[e>1])

根据定义式,f(1)+S(n,0) 就是答案。

如果记 Fprime(n)=pnf(p),那么:

S(n,i)=Fprime(n)Fprime(pi)+k>i,pkn,peknf(pek)(S(npek,k)+[e>1])

我们需要解决 Fprime(n) 的问题:

假设 f(p) 为一多项式,设 f(p)=mk=0akpk

Fprime(n)=pnf(p)=pnmk=0akpk=mk=0akpnpk

于是我们只需要求出 pnpk 即可。

定义函数 gk(n,i) 为:

gk(n,i)=nx=1[(xP)(lpf(x)>pi)]xk

尝试递推 gk(n,i)

gk(n,i)=nx=1[(xP)(lpf(x)>pi)]xk=nx=1[(xP)(lpf(x)>pi1)]xknx=1[(xP)(lpf(x)=pi)]xk=gk(n,i1)(n/pi)y=1[lpf(y)pi](ypi)k=gk(n,i1)pki(n/pi)y=1[lpf(y)>pi1]yk=gk(n,i1)pki((n/pi)y=1[(yP)(lpf(y)>pi1)]yk(n/pi)y=1[(yP)(lpf(y)pi1)]yk)=gk(n,i1)pki((n/pi)y=1[(yP)(lpf(y)>pi1)]ykpi1y=1[yP]yk)=gk(n,i1)pki((n/pi)y=1[(yP)(lpf(y)>pi1)]ykpi1y=1[(yP)(lpf(y)>pi1)]yk)=gk(n,i1)pki(gk((n/pi),i1)gk(pi1,i1))

大概意思就是说,gk(n,i) 一定是由 gk(n,i1) 减去最小质因数恰好是 pi 的合数 x 的贡献得到,于是枚举最小质因数大于等于 pi 的数 y 使得 x=piy,也就是 gk((n/pi),i1),但还需减去 y 为小于 pi 的质数的贡献,即 gk(pi1,i1)

注意倒数第 4 行推到倒数第 3 行时是默认了 pi1(n/pi)=npi 的,因为如果 pi1>npi 的话,就有 pi1+1>npi+1>npi,于是 npi<pi1+1<pi,则 p2i>n,就不存在最小质因数恰好是 pi 的合数 x,此时直接 gk(n,i)=gk(n,i1) 即可。

那么:

gk(n,i)={gk(n,i1)if p2i>ngk(n,i1)pki(gk((n/pi),i1)gk(pi1,i1))if p2in

于是只要我们知道 gk(n,0) 就可以递推了。

gk(n,0)=nx=1[(xP)(lpf(x)>p0)]xk=nx=2xk

这是自然数幂求和,直接 O(k) 做即可。

于是 pnpk=gk(n,π(n)) 即可。(其中 π(n) 表示小于等于 n 的质数个数)

于是 Fprime(n) 就被我们解决了,于是就可以递推 S(n,i) 了。

时间复杂度不会……

口胡 min_25 筛的主要思路(主要方便自己记):

ni=1f(i),我们先对 1n 分成质数和合数,合数的部分我们通过枚举最小质因数递推,关键在于质数的部分,即 pnf(p)。然后 f(p) 是低次多项式,可以拆成不同次分开处理,即求 pnpk。然后发现这个时候 ni=1ik 是好算的,于是又反过来,用全体数减去合数得到质数的答案,合数的部分也是枚举最小质因数递推。

一些代码实现的细节:

  • Fprime(pi)gk(pi1,i1)=pi1y=1[yP]yk 可以线性筛预处理。

  • 注意到求 S(x,y) 时,向下递归的形式是 S((x/b),),其中 b 为某一个正整数。于是我们就猜想:是否所有求 S(x,y) 时,x 都能表示为 nc 的形式。答案当然是能。g(x,y) 也是同理。

    于是出现在 Sg 第一维的 x 的取值只能是:(n/1),(n/2),(n/3),,(n/n),共 O(n) 种。

    那么我们整除分块,将这些取值离散化,然后就可以把空间复杂度降到只有 O(n)。将每一种取值给一个标号,记取值 v 的标号为 id(v)

    显然如果我们真的要存 id(v) 的话就需要用 map,但我们有更好的方法。

    具体来说,对于 x=(n/i),若 xn,那么我们令 id1(x)id(x);若 x>n,那么我们令 id2(n/x)id(x)

    查询 x 的标号的时候我们就直接判断 xn 的大小关系再进入 id1id2 查询即可。

多项式

下面一部分专题都会与多项式相关。

原根

参考了 cmd 的博客。

不得不说 cmd 是真的卷王。

  • :对于任意的有限群 G={e,a1,,an},对于任意的 aG 都存在一个正整数常数 ord(a) 使得 aord(a)=e,称 ord(a)a 的阶。

    证明:

    • 引理:对于群 G 以及 a,bG,若 ab=a,那么 bG 的单位元。

      证明:只需证对于其他的 aG 也满足 ab=a 即可。

    构造 a,a2,,an+1,由于这 n+1 个元素都属于 G,所以必有二者相等,设为 ax=ay(x<y),那么 axayx=ax。再根据引理可证 ayx 为单位元。

    意思是 a 的若干次幂在有限群 G 中一定至少构成一个 ρ 字形,那么 a 的环的大小次幂就是单位元。

    推论 1:a 的若干次幂不仅是 ρ 字形,而且就是一个环,ord(a) 就是环的大小。

    推论 2:a,a2,,aord(a) 两两不同。

    证明:由上面证明过程容易得到。

  • 整数模 n 乘法群(模 n 既约剩余类)

    这里我们用 [a] 表示模 na 同余的剩余类。

    如果一个模 n 的剩余类 [a] 中的所有数都与 n 互质(等价于 (n,a)=1),那么我们称 [a] 为一个模 n 既约剩余类。

    所有的模 n 既约剩余类在剩余类的乘法运算下组成一个乘法群,称为整数模 n 乘法群,姑且记作 Gn

    容易验证 Gn 满足群公理:

    • 封闭性:若 [a],[b]Gn,则 ab 也与 n 互质,故 [a][b]=[ab]Gn

    • 结合律:由乘法运算法则不难得到。

    • 存在单位元:[1] 肯定属于 Gn,它是单位元。

    • 存在逆元:即对于任意 [a]Gn,都存在 (x,n)=1ax1(modn)

      转化为 ax+ny=1,由裴蜀定理可知有解当且仅当 (a,n)=1,得证。

下面为了方便和直观,建议你可以直接将模 na 剩余类当成数字 a,即直接将 Gn 看成所有小于等于 n 且与 n 互质的正整数在模 n 意义的乘法下组成的群。

那么对于 aGn,它的阶就是最小的正整数 ord(a) 使得 aord(a)1(modp),即幂的最小循环节,由群的封闭性可知它的上界为 |Gn|=φ(n)

  • 循环群:若一个群 G 的每一个元都是 G 的某一个固定元 a 的若干次幂,则称 G 为循环群,记作 G={am|mZ}a 称为 G 的一个生成元。

容易看出 ord(a)=|G|,也容易得到一个群是循环群当且仅当存在 aG 满足 ord(a)=|G|

循环群分两种:

  • |G|=,则 G 的生成元有且仅有两个,分别为 aa1

    证明:此时 G 与整数加法群同构(考虑幂乘法和指数加法的对应关系),而整数加法群只有两个生成元 11

  • |G|=n,则 G 的生成元有 φ(n) 个,它们为 {ak|(k,n)=1}

    证明:考虑 a 的幂,这构成一个大小为 n 的、恰好包含 G 中所有元素的环。

    那么 ak 的若干次幂相当于在这个环上走若干次每次走 k 步,容易知道这样走也会构成一个大小为 ngcd(k,n) 的环。

    所以若 (k,n)=1,那么 ak 一定是生成元。否则 ak 一定不是生成元。

    而且 G 中的任意一个元素都可以被表示成 ak 的形式,所以所有可能的生成元都被我们考虑到了。

    推论:设 bGb=ak,那么 ord(b)=ngcd(k,n)。证明由上面证明过程易得。

接下来需要考虑的是第二种循环群。

  • 原根:对于 p,若 Gp 为循环群,则称 Gp 的生成元为 p 的原根。

    换言之,对于 gGp,若满足 ord(g)=φ(p),那么我们称 gp 的原根。

那么若 p 有原根,个数为 φ(|Gp|)=φ(φ(p))。若一个数与 p 互质,它肯定能用原根的若干次幂表示。

一个结论是当 p=2,4,pc,2pcp 为奇质数)时,Gp 才是循环群,p 才有原根。

接下来的问题是:假设我们已经判定了 p 有原根,然后如何求 p 的原根。

一个结论是 p 的最小原根不超过 p0.25

那么我们可以从小往大枚举数 g 满足 (g,p)=1,并判断它是否为 p 的原根,只需判定它的阶是否为 φ(p) 即可。

枚举阶快速幂判定肯定是慢的,更优美的做法是:我们并不需要求出 g 的阶的准确值,只需要知道它的阶是否为 φ(p) 即可。

由循环群中的推论可知,g 的阶一定是 φ(p) 的因数。

又注意到若 gk1(modp),那么 gik1(modp)

所以 g 的阶为 φ(p) 的严格因数的判定条件就可以转化为 i[1,m],gppi1(modp),其中 p1,,pmp 的质因数。

于是单次判定某个 g 的复杂度就降为 O(ω(p)logp),找某个原根的总复杂度就是 O(p0.25ω(p)logp)

Bluestein 算法

给出多项式 A(x)=ni=0aixic,求 A(1),A(c),A(c2), 的算法。

FFT 做的是 c2 的幂次的单位根的特殊情况。而这种算法对 c 没有特殊性质。

关键在于 ki=(k+i2)(k2)(i2),于是:

A(ck)=ni=0aicki=ni=0aic(k+i2)(k2)(i2)=c(k2)ni=0aic(i2)c(k+i2)

减法卷积即可。

多项式求逆

给定多项式 F(x),求多项式 G(x) 使得 F(x)G(x)1(modxn),其中 F(x)G(x) 的系数对一个数 p 取模。(对于一个多项式 F(x)F(x)modxn 的意思是只看 F(x) 中的第 0 项到第 n1 项)

用递归求解。(以下的所有多项式都是在系数模了 p 意义下的)

首先假设我们已经求出了 F(x)H(x)1(modxn2)(记为 1 式),现在要求 F(x)G(x)1(modxn)

首先如果有 F(x)G(x)1(modxn),那么一定有 F(x)G(x)1(modxn2)(记为 2 式),因为等号右边的那个 1 只能在常数项出现,其他项的系数都是 0

1 式减 2 式得 F(x)(H(x)G(x))0(modxn2)

由于 F(x)0(modxn2),所以 H(x)G(x)0(modxn2)

然后等式两边平方,因为 H(x)G(x)0(modxn2),即 H(x)G(x) 的第 0 项到第 n21 项系数都是 0,那么 (H(x)G(x))2 肯定满足第 0 项到第 n1 项系数都是 0,所以有:

H(x)2+G(x)22G(x)H(x)0(modxn)

两边同时乘 F(x) 得:

F(x)H(x)2+F(x)G(x)22F(x)G(x)H(x)0(modxn)F(x)H(x)2+G(x)2H(x)0(modxn)

上面第二步的化简是用 F(x)G(x)1(modxn) 化简的,注意不能用 F(x)H(x)1(modxn2),因为两个式子 mod 的东西不一样。

那么就可以得到:G(x)=2H(x)F(x)H(x)2

那么我们就能通过 n2 的答案求出 n 时的答案了,所以一直向下递归。

最后当递归到 1 的时候,要求 F(x)G(x)1(modx1),也就是 F(x) 的常数项和 G(x) 的常数项乘起来模 p1,那么只用求 F(x) 常数项的逆元就好了。

总时间复杂度为:(设 n=2m,以下的 log 均以 2 为底)

m1i=02ilog(2i)<m1i=02ilog(n)=(2m1+11)log(n)=(n1)log(n)<nlogn

多项式开根

跟多项式求逆差不多,用递归求解。

假设我们现在要求 G(x) 使得 G(x)2F(x)(modxn),已经求出了 H(x)2F(x)(modxn2)。(记为 1 式)

显然若 G(x)2F(x)(modxn),则 G(x)F(x)H(x)(modxn2)

G(x)H(x)(modxn2)G(x)H(x)0(modxn2)(G(x)H(x))20(modxn)G(x)2+H(x)22G(x)H(x)0(modxn)F(x)+H(x)22G(x)H(x)0(modxn)G(x)F(x)+H(x)22H(x)(modxn)

然后就能递归求逆做了。

时间复杂度 O(nlogn)

多项式求导

f(x)=i0aixi,则:

f(x)=limd0i0ai(x+d)iaixid=limd0i0ai(x+d)ixid

我们现在只看 (x+d)ixid 怎么求:

(x+d)ixid=ij=0(ij)xjdijxid=i1j=0(ij)xjdij+xid0xid=i1j=0(ij)xjdijd=i1j=0(ij)xjdij1

j<i1 时,ij1>0,又由于 d 趋近于 0,则 dij1=0

所以:

i1j=0(ij)xjdij1=(ii1)xi1d0=ixi1

那么:

f(x)=limd0i0ai(x+d)ixid=i1aiixi1

同样的,若知道 f(x)=i0aixi,那么 f(x)=i1ai1ixi

多项式 ln

F(x)=lnx,那么我们要求的即为 G(x)F(A(x))(modxn)

对两边同时求导:

G(x)F(A(x))A(x)A(x)A(x)(modxn)

直接求出 G(x) 再积分即可。

多项式 exp

泰勒展开

我们为了近似表达一函数 f(x),构造另一函数 g(x),使得 f(x)=g(x),f(x)=g(x),f(n)(x)=g(n)(x)

g(x)=a0+a1x+a2x2++anxn

由于 f(x)=g(x),代入 x=0 可得 f(0)=g(0),又 g(x)=a0+a1x+a2x2++anxn,得 a0=f(0)

由于 f(x)=g(x),代入 x=0 可得 f(0)=g(0),又 g(x)=1a1+2a2x++nanxn1,得 a1=f(0)1!

由于 f(x)=g(x),代入 x=0 可得 f(0)=g(0),又 g(x)=2a2+6a3x+n(n1)anxn2,得 a2=f(0)2!

……

最后得到 an=f(n)(0)n!,故:

g(x)=f(0)+f(0)1!x+f(0)2!x2++f(n)(0)n!xn

这是代入 x=0 的特殊情况,而我们代入 x=x0 也是同理的,有:

g(x)=f(x0)+f(x0)1!(xx0)+f(x0)2!(xx0)2++f(n)(x0)n!(xx0)n

n 时有 f(x)=g(x)

多项式牛顿迭代

求一类方程的解:

F(G(x))0(modxn)

假设我们已经得知了 G0(x)G(x)(modxn2),要求 G(x)modxn

F(G(x))G0(x) 处泰勒展开:

F(G(x))=n=0F(n)(G0(x))n!(G(x)G0(x))n

代入 G(x)=G1(x) 得:

F(G1(x))=n=0F(n)(G0(x))n!(G1(x)G0(x))n0(modxn)

又由于 G0(x)G(x)(modxn2),则:

G0(x)G(x)(modxn2)G0(x)G(x)0(modxn2)(G0(x)G(x))20(modxn)

所以次数大于等于 2 的项都被消掉了。

那么:

n=0F(n)(G0(x))n!(G(x)G0(x))n0(modxn)F(G0(x))+F(G0(x))(G(x)G0(x))0(modxn)

F(G0(x)) 常数项都非零时,得到迭代公式:

G(x)G0(x)F(G0(x))F(G0(x))(modxn)

F(G0(x))k 项为 0 且第 k+1 项非零时(此时 F(G0(x))k 项也应为 0),一般来说 k 都是常数,那么牛顿迭代的时候考虑由 G(x)modxk+n2 推到 G(x)modxk+n

这是因为对于 A(x)B(x)C(x)(modxn),其中 A,Ck 项为 0 且第 k+1 项非零时,只能得到 B(x)C(x)A(x)(modxnk)

多项式 exp

B(x)eA(x)(modxn)lnB(x)A(x)0(modxn)

那么就是要求函数 F(G(x))=lnG(x)A(x) 的零点,即 F(G(x))0(modxn)G(x) 的解。

套用牛顿迭代,假设我们已经得知了 G0(x)G(x)(modxn2),要求 G1(x)G(x)(modxn)

根据迭代公式,得:

G1(x)G0(x)F(G0(x))F(G0(x))(modxn)G0(x)lnG0(x)A(x)1G0(x)(modxn)G0(x)(1lnG0(x)+A(x))(modxn)

那么就可以求了。

时间复杂度 O(nlogn)

多项式带余除法

给定一个 n 次多项式 F(x) 和一个 m 次多项式 G(x),要求求出多项式 Q(x)R(x),满足下面的条件:

  • Q(x) 次数为 nmR(x) 次数小于 m
  • F(x)=Q(x)×G(x)+R(x)

考虑先求出商,再求余数。

A(x) 为一 n 次多项式,定义 Ar(x)=xnA(1x),易知 Ar[i]=A[ni]

F(x)=Q(x)×G(x)+R(x)F(1x)=Q(1x)×G(1x)+R(1x)xnF(1x)=xnmQ(1x)×xmG(1x)+xnR(1x)Fr(x)=Qr(x)×Gr(x)+xnm+1Rr(x)Fr(x)Qr(x)×Gr(x)(modxnm+1)Qr(x)Gr(x)×F1r(x)(modxnm+1)

然后直接求出 Qr(x),再求出 Q(x)R(x) 即可。

时间复杂度 O(nlogn)

多项式多点求值

给定一个 n 次多项式 F(x),现在请你对于 i[1,m],求出 F(ai)

注意到多项式取模 F(x)=Q(x)G(x)+R(x) 中,若 G(x0)=0,则 R(x0)=F(x0)

所以我们考虑对于 i 构造 Gi(x)=xai,那么显然 F(ai)=F(ai)modGi(ai)

所以我们只需要对于每一个 i 求出 F(x)modGi(x) 即可,注意到此时模出来是一个常数,那么就是 F(ai)。不妨设 F(x)=Qi(x)Gi(x)+Ri(x)

考虑如何求 Ri(x)

考虑分治,设当前要求出对于所有 i[L,R]F(x)modGi(x),那么我们先让 F(x)Ri=LGi(x) 取模,然后在往 [L,mid][mid+1,R] 递归。容易得知这样做不会影响答案,而且每次能将 F(x) 的次数减少一半,时间复杂度 O(nlogn+mlog2m)(带上 nlogn 的原因是一开始还要将 F(x)mi=1Gi(x) 取模,这一次消耗的时间是 O(nlogn) 的)。

但鉴于多项式取模的极大常数,这个可能连 105 都跑不过去。

有一种常数更小的做法:

重新分析一下,Ri(x)=F(x)Qi(x)Gi(x),而 Ri(x) 只有常数项,所以如果我们知道了 Qi(x) 的常数项,就能知道 Ri(x) 了。

考虑多项式取模是如何求出 Qi(x) 的:Qi,r(x)Fr(x)G1i,r(x)(modxnm+1),即 Qi,r(x)Fr(x)G1i,r(x)(modxn)(这里下标带 r 是指反转)。

仍然考虑分治,设 Gs(x)=Ri=LGi(x)G0(x)=midi=LGi(x)G1(x)=Ri=mid+1Gi(x)

那么易知 Gs(x)=G0(x)G1(x),则 Gs(1x)=G0(1x)G1(1x)xRL+1Gs(1x)=xmidL+1G0(1x)xRmidG1(1x),即 Gs,r(x)=G0,r(x)G1,r(x)

那么假设我们已经知道了 Fr(x)G1s,r(x) 的结果,那么我们只需要对这个结果乘上 G1,r(x) 即可知道 Fr(x)G10,r(x) 的值;对这个结果乘上 G0,r(x) 即可知道 Fr(x)G11,r(x) 的值。递归到底层即可。

但这样时间复杂度是不对的,因为我们为了保证底层结果的正确,每次乘法都要在模 xn 意义下进行。

但注意到我们只需要求 Qi(x) 的常数项,即 [xn1]Qi,r(x),也就是说只有某一项可能对最高项产生贡献才需要保留,否则可以直接舍弃。

那么假设从当前到底层还要乘上的 G(x) 之积的最高次为 k 次,那么当前的 Q(x) 只需要保留最高的 k+1 项,因为剩下的项都不会对最后的 Q(x) 的最高项有贡献。

具体来说,递归到区间 [L,R]Q(x) 只需要保留最高的 RL+1 项。

这样时间复杂度就对了。

然后我们求出 Q(x) 后根据 Ri(x)=F(x)Qi(x)Gi(x) 算出 R(x) 即可。

基于转置原理的多项式多点求值算法

写得有点乱。

先令多项式项数和多点求值点数相同,均为 n,若不同补齐即可。

对于一个 n1 次多项式 m1i=0fixi,我们将其看做一个列向量 f=(f0,,fm1)T。那么对于 a0,,an1 多点求值的过程就相当于是计算:

[1a0a20an101a1a21an111an1a2n1an1n1]f

记左边的矩阵为 V

考虑 VTf=g,我们写出 gi 的生成函数:

n1i=0gixi=n1i=0xin1j=0aijfj=n1j=0fjn1i=0aijxi=n1j=0fj1ajxmodxn

可以使用分治 NTT 计算,我们先求出和式的分子,再乘上和式的分母的逆即可。

但这对我们计算 Vf 有什么帮助呢?

这就要用到转置原理。其核心思想是:对于矩阵 V 和任一向量 f,为了优化计算 Vf,我们可以先考察计算 VTf 的方法。然后我们把计算 VTf 的过程展开,看成是 EkE1f,其中 Ei 均为初等矩阵。那么 Vf s 的效果是使 f 的某个位置乘上 c,那么 ETf 的效果也一样。

  • Ef 的效果是交换 f 中的两个位置,那么 ETf 的效果也一样。
  • Ef 的效果是使 f 的某个位置 x 加上另一个位置 y 乘上 c(即 x+=cy),那么 ETf 的效果为使位置 y 加上位置 xc(即 y+=cx)。

也就是说,我们把计算 VTf 的过程 “倒过来”,再对每一个操作 “转置” 一下,就可以得到计算 Vf 的操作过程了。

那么现在考虑分治 NTT 的过程,理论上由于它计算的是 VTf,所以过程中应该是不断在对当前向量 u(初始为 f)做线性变换。可能会令人绕晕的一点是,分治 NTT 的过程中都是多项式在相乘,哪里出现了线性变换?但实质上是多项式的系数列表(即生成函数对应的原数列)在做线性变换:对于常多项式 A(次数为 m)和多项式 f(次数为 n)相乘,可以看做是在做类似于这样的变换:

[A00A1A00AmAm1A000AmA1A00][f0f1fn0]=[g0g1gn+m]

那么我们会将 Aifj 贡献到 gi+j,即 gi+j+=Aifj,注意这里应有 jn,因为在操作过程中我们是对整个向量的 f0,,fn 部分提取出来做多项式乘法,fn 后面的那些位置并不是 0。转置之后就是 fj+=Aigi+j,其中需满足 jn,这恰好对应着减法卷积,记为 A×Tf。(注意我们当然不可能真的把每次加减乘除交换操作全部丢到一个队列里面然后反过来做。我们要整体考虑一个操作的 “转置” 是什么)

考虑 NTT 中的过程:

  1. 分治求分子。假设当前分治到 [l,r]。已经求得 [l,mid] 的答案 L=ul,mid[mid+1,r] 的答案 R=umid+1,r。设 Al=midi=l(1aix),Ar=ri=mid+1(1aix)

    那么当前的答案 F=Ar×L+Al×R

  2. 已经求出了分子 P。设 Q=1n1i=0(1aix)modxn,执行操作 PQ×Pmodxn

那么整个过程转置之后就是:

  1. 执行操作 PQ×TP,注意由于原来有取模所以这里转置后的多项式乘法会有所不同,具体表现在 fj+=Aigi+j 中还需满足 i+j<n(不过本来大于等于 n 也不会有项) 。然后将 P 扔进分治递归。

  2. 假设当前分治到 [l,r]。原来我们进行的是 F=Ar×L+Al×RL=ul,mid,R=umid+1,r),我们现在要把它转置回去。

    可以看成是在同一个矩阵里同时进行了操作 Fi+j+=Ar,iLjFi+j+=Al,iRj(注意两边的 j 都各有限制范围),那么转置回来就是 Lj+=Ar,iFi+jRj+=Al,iFi+j。即 L=Ar×TF,R=Al×TF

    然后递归下去做即可。

时间复杂度 O(nlog2n),常数较小。

多项式快速插值

洛必达法则

众所周知,两个无穷小之比或两个无穷大之比的极限可能存在,也可能不存在。因此,求这类极限时往往需要适当的变形,转化成可利用极限运算法则或重要极限的形式进行计算。洛必达法则便是应用于这类极限计算的通用方法。

——摘自百度百科

洛必达法则分为两种 0/0 型和 / 型:

  1. 0/0 型洛必达法则:

    若函数 f(x),g(x) 满足以下条件:

    • limxaf(x)=0limxag(x)=0

    • 在点 a 的某去心邻域内两者都可导,且 g(x)0

      注意,这里只需要存在去心邻域即可,我们无需关心去心邻域的大小,因为我们只需要存在 f(x),g(x)xa),下面会讲。

    则:

    limxaf(x)g(x)=limxaf(x)g(x)

  2. / 型洛必达法则:

    若函数 f(x),g(x) 满足以下条件:

    • limxaf(x)=limxag(x)=

    • 在点 a 的某去心邻域内两者都可导,且 g(x)0。注意,这里同样只需要存在去心邻域即可,原因同上。

    则:

    limxaf(x)g(x)=limxaf(x)g(x)

证明:

考虑构造 u(x)=(g(x),f(x)),这个函数是一个 RR2 的映射,即一条数轴映射到一个平面坐标系。

我们考虑求 u(x) 是什么:

u(x)=limΔx0f(x+Δx)f(x)g(x+Δx)g(x)=limΔx0f(x+Δx)f(x)Δxg(x+Δx)g(x)Δx=limΔx0f(x)g(x)=f(x)g(x)

对于一个非(0,0) 的点 A(x,y),我们考虑定义 A 的 “零点线” 为过 (0,0)A 的直线,易知这条直线的斜率为 yx

那么 u(x) 的零点线的斜率就是 f(x)g(x)

显然我们现在已经构造出 f(x)g(x)f(x)g(x) 的几何意义了,接下来就看什么时候他们相等了。

首先 f(x)g(x)u(x) 处的切线的斜率,f(x)g(x)u(x) 的零点线的斜率,如果他们相等,要么就是切线和零点线重合,要么就是切线和零点线平行。

  1. 切线和零点线重合(0/0 型):

    大前提是 u(x)(0,0),即存在 limxaf(x)=0limxag(x)=0 的情况。

    首先注意到切线和零点线都是过 u(x) 的,而零点线还过 (0,0),所以如果切线也过 (0,0) 那就能满足切线和零点线重合了。

    易知当 u(x)(0,0) 时,切线肯定就是零点线。

    所以有 limu(x)(0,0)f(x)g(x)=limu(x)(0,0)f(x)g(x),即为 0/0 型的洛必达法则。

  2. 切线和零点线平行(/ 型):

    大前提是 u(x)(,),即存在 limxaf(x)=limxag(x)= 的情况。

    你可能会产生疑惑:既然切线和零点线都过 u(x),那么他们怎么可能平行呢?

    但我们有这么一种特殊情况:相交于无穷远点的两条直线是平行的。

    得到当 u(x)(,) 时,切线和零点线是趋于平行的,因为他们相交于一无穷远点 u(x)

    但这个 “相交于无穷远点” 的解释对于我来说比较难以理解。

    所以有 limu(x)(,)f(x)g(x)=limu(x)(,)f(x)g(x),即为 / 型的洛必达法则。

证毕。

(上述的证明比较感性,目的只是帮助你记忆,真正正确严格的证明请自行查阅资料)

多项式快速插值

先考虑用拉格朗日插值暴力搞出这个多项式:

f(x)=ni=1yijixxjxixj

显然这样做时间是无法接受的,考虑优化。

我们将它分为两个部分去计算:(因为分母的部分是可以直接计算出来的,接下来会讲)

f(x)=ni=1yiji(xixj)ji(xxj)

先看到左边的那个式子,yi 是个常数,我们暂时不用管它,接下来看分母:ji(xixj)

如果我们设 g(x)=ni=1(xxi),那么分母即为把 x=xi 代入 g(x)xxi 得到的值。但代入后分子分母都是 0,怎么求啊……

这就要用到 0/0 型洛必达法则了:

limxxig(x)xxi=limxxig(x)(xxi)=limxxig(x)=g(xi)

那么我们只需要用分治 NTT 求出 g(x),再求导得出 g(x),再代入 x1,x2,,xn 多点求值即可。

考虑分治计算最后的式子,定义 fl,r(x) 为:

fl,r(x)=ri=lyinj=1,ji(xixj)rj=l,ji(xxj)=ri=lyig(xi)rj=l,ji(xxj)

容易得到:

fl,r(x)=fl,mid(x)[rj=mid+1(xxj)]+fmid+1,r(x)[midj=l(xxj)]

然后就可以分治求了。

拉格朗日反演

对于形式幂级数(以下简称幂级数) F(x),记 F[i]=[xi]F(x)

幂级数复合:(FG)(x)=F(G(x))=i0F[i]G(x)i。可以看成一个幂级数变换。

常数项为 0,一次项非 0 的幂级数集合 P 在复合运算下形成群:

  • 封闭性:对于任意 F,GP(FG)(x) 常数项为 0,一次项系数为 F[1]G[1]0

  • 结合律:映射的复合显然有结合律。

  • 单位元:F(x)=x

  • 逆元:即对于任意的 FP,都存在 F<1>P 满足 (F<1>F)(x)=x。根据幂级数复合的定义 (F<1>F)(x)=i0F<1>[i]F(x)i=x 递推构造即可得到唯一的 F<1>

补充的几点:

  • 注意幂级数复合并不满足交换律,但满足 (F<1>F)(x)=(FF<1>)(x)=x,称 F,F<1> 互为复合逆。

  • 为什么一定要求常数项为 0、一次项非 0 才能形成群?

    • 假设常数项不为 0。那么若 F(x) 不是有限项非 0(FG)(x)=i0F[i]G(x)i 就不收敛了,或者说不满足封闭性了。无穷和式 iFi(x) 收敛的意思是对于任意的 k,都存在一个位置 n 使得对于任意 nn 都有 [xk]Fn(x)=0

    • 假设一次项为 0,那就甚至连单位元都没有了。

接下来,我们引入分式域,即引入 x 的负整数次幂这种东西。接下来我们对于幂级数的操作都在分式域上进行。

分式域上的幂级数加减乘仍然是良定义的。而对于分式域上的逆,考虑要求 F(x) 的逆,我们将 F(x) 进行适当的平移使得 F(x) 变为整式,即找到一个整数 k 使得 F(x)=xkG(x)G(x) 为常数项非 0 的整式,就能得到 F(x)1=xkG(x)1

分式域上的求导、积分仍然是良定义的,不过有一个等会要用到的性质就是:对于任意分式域上的幂级数 F(x)[x1]F(x)=0

  • 引理 1:对于任意的 F(x)P,有:

    [x1]F(x)F(x)k=[k=1]

    证明:当 k1 时,F(x)F(x)k=(1k+1F(x)k+1),再根据刚刚提到的性质即可得证。

    k=1 时,[x1]F(x)F(x)k=[x1]F(x)F(x)=[x0]F(x)F(x)/x=F[1]F[1]=1

  • 拉格朗日反演:对于 F(x),G(x)P,若 F,G 互为复合逆,那么有:

    [xn]G(x)=1n[x1]F(x)n

    证明:考虑利用引理1把 G[n] 提出来:

    G(F)=xi0G[i]Fi=xi0G[i]Fin1F=xFn1F[x1]i0G[i]Fin1F=[x1]xFn1Fi0G[i][in1=1]=[x1]xFn1FG[n]=[x1]xFn1FG[n]=[x2]1n(Fn)G[n]=1n[x1]Fn

    计算方法:一个更方便的形式是 1n[xn1](F(x)/x)n,于是我们可以直接先求逆然后做多项式快速幂就能 O(nlogn) 计算 G[n] 了。

  • 扩展拉格朗日反演:对于 F(x)P 和另外一个无要求的幂级数 H,若 T(F(x))=H(x)F,G 互为复合逆,有:

    [xn]T(x)=[xn]H(G(x))=1n[x1]H(x)F(x)n

    证明:也是类似的:

    T(F)=Hi0T[i]Fi=H[x1]i0T[i]Fin1F=[x1]HFn1FT[n]=[x1]HFn1FT[n]=[x1]1nH(Fn)T[n]=1niH[i]×(Fn)[1i]T[n]=1ni(i)H[i]×Fn[i]T[n]=1niH[i1]×Fn[i]T[n]=1n[x1]H×Fn

    计算方法:也是类似的变成 [xn1]H×(F(x)/x)n 即可 O(nlogn) 求解单项 T[n]

    应用:目前遇到了两种:

    • 给定两个幂级数 F(x)PH(x),要求出描述他们之间的关系 T(F(x))=H(x)T(x) 的某一项系数。

    • 给定一个幂级数 F(x)PH(x),要求计算 H(F(x)) 的某一项系数。

      例:要求计算 [xn]B(x)k,其中 B(x)=114x2x 为卡特兰数生成函数。

      这里显然是设 H(x)=xk,但我们不能直接对 B(x) 求符合逆,因为它常数项不为 0,所以我们令 B(x)=114x2,变为计算 [xn]xkH(B(x))=[xn+k]H(B(x)),其中 B(x)P

      接下来是计算 B(x) 的复合逆 A(x)

      y=114x212y=14x4y24y+1=14xx=yy2

      于是得到 A(x)=xx2,根据扩展拉格朗日反演:

       [xn]H(B(x)))=1n[xn1]H(x)(xA(x))n=1n[xn1]kxk1(11x)n=kn[xnk](11x)n=kn(2nk1n1)[xn+k]H(B(x))=kn+k(2n+k1n+k1)

FWT

位运算卷积(FWT)

子集卷积

对于数组 A,B,求数组 C 使得 Ck=i|j=k,i&j=0AiBj

直观地看上去就是 Ck=ikAiBki,所以称作子集卷积。

下面用 |i| 表示 popcount(i)

注意到 i|j=k,i&j=0 等价于 i|j=k,|i|+|j|=|k|

我们设:

ai,j={Ajif i=|j|0if i|j|

对于 bi,j 的定义同理。

那我们要求的实际是:

Ck=i|j=k,|i|+|j|=|k|AiBj=p+q=|k|i|j=kap,ibq,j=p+q=|k|OR(ap,bq)k=[p+q=|k|OR(ap,bq)]k

于是我们设 cr,k=[p+q=rOR(ap,bq)]k,那么我们最后要求的答案是 C={c|i|,i}

那么我们可以先 O(logn) 枚举 p,把每个 ap 的 FWT 值给算出来。同理我们也把每个 bq 的 FWT 的值都算出来。然后再 O(log2n) 枚举 p,q,把每个 cr 的 FWT 值给算出来。最后再 O(logn) 枚举 r,做一遍 IFWT 把 cr 给逆推回来,那么也就得到了 C

总共的时间复杂度为 O(nlog2n)

个人认为这个算法的思想是把 O(n) 的条件 i&j=k 转化成 O(logn) 的条件 |i|+|j|=|k|,最后再利用 FWT 把时间复杂度从 O(n2log2n) 降到了 O(nlog2n)

代码可参考【XSY3020】CF914G Sum the Fibonacci

一些特殊形式的求法

一、求 nk=1xkij=kaibj

平常的 FFT 是求 nk=1xki+j=kaibj,那么我现在让你求 nk=1xkij=kaibj

S(k)=ij=kaibj,那么题目是要求 nk=1xkS(k)

^ai=ani,那么:

S(k)=ij=kaibj=(ni)j=k^aibj=i+j=nk^aibj

那么:

S(nk)=i+j=n(nk)^aibj=i+j=k^aibj

那么就可以设多项式 A={^ai}B={bi}C=A×B,则 S(nk)=[xk]C

所以将 C 翻转一下就是我们要求的了。

拉格朗日插值

原理

给出 n 个点 (xi,yi),可知这 n 个点唯一确定一个多项式 f(x)

现在询问 k,求 f(k)

用高斯消元可以做到预处理 O(n3),每次询问 O(n)

但是现在只有一次询问,且 n 很大。

所以我们考虑用询问更快的方法求解。

拉格朗日插值是通过构造的方法,在 O(n2) 的时间内进行询问。

设拉格朗日基本多项式为:

i(x)=nj=1,jixxjxixj

注意到当 x=xi 时,i(x)=1;当 x=xjji)时,i(x)=0

那么就能把这个多项式 f(x) 构造出来了:

f(x)=ni=1yii(x)

显然,这个多项式满足对于任意的 if(xi)=yi

那么这个多项式就是我们要找的多项式。

minmax 容斥

minmax 容斥

S 为一集合,min(S) 表示集合 S 的最小元素,max(S) 表示集合 S 的最大元素。有:

max(S)=TS,T(1)|T|1min(T)

minmax 位置反过来也是一样的。

kthminmax 容斥

S 为一集合,mink(S) 表示集合 S 的第 k 小元素,maxk(S) 表示集合 S 的第 k 大元素。有:

maxk(S)=TS,T(1)|T|k(|T|1k1)min(T)

改成 minkmax 相关的式子也是一样的。

证明:

下面给出的是 kthminmax 容斥的证明,而 minmax 容斥的证明类似。

先设容斥系数 f(x) 使得:

maxk(S)=TS,Tf(|T|)min(T)

n=|S|,考虑 S 的第 x 小的数 v 在式子左右两边的贡献:

  • 在左边贡献为 v[x=nk+1]

  • 在右边,我们枚举所有包含 v 且以 v 作为最小值的 T,贡献为 nxi=0(nxi)f(i+1)v

于是:

v[x=nk+1]=nxi=0(nxi)f(i+1)v[x=nk+1]=nxi=0(nxi)f(i+1)[nx=k1]=nxi=0(nxi)f(i+1)

F(x)=f(x+1)G(x)=[x=k1],令 n=nx,于是:

G(n)=ni=0(ni)F(i)

根据二项式反演:

F(n)=ni=0(1)ni(ni)G(i)

带回去:

f(n+1)=ni=0(1)ni(ni)[i=k1]=(1)nk+1(nk1)

故:

f(n)=(1)nk(n1k1)

证毕。

上面最开始的两个式子套上期望也是成立的。口胡证明:因为期望=∑(枚举每种情况)概率×贡献,而对于每种情况都适用于上面不带期望的式子,再根据期望的线性性可推得成立。

E(max(S))=TS,T(1)|T|1E(min(T))

E(maxk(S))=TS,T(1)|T|k(|T|1k1)E(min(T))

斯特林数

第二类斯特林数

第二类斯特林数 {nm} 表示将 n 个不同的球分到 m 个没有区别的袋子里,每个袋子里不能为空,且每个袋子里的球无序的方案数。

递推公式

{n0}=[n=0]{nm}={n1m1}+m{n1m}

证明:从组合意义证明,我们考虑前 n1 个球已经装好了,对于最后一个球来说,它有可能单独新放进一个空的袋子,也可能在非空的袋子中任选一个。

通项公式

{nm}=1m!mi=0(1)i(mi)(mi)n

感性理解是:容斥,先枚举有 i 个袋子是空的,再枚举是哪 i 个袋子,然后 n 个球就随便放进剩下的 mi 的袋子即可。又由于袋子是无序的,所以需要除以 m!

拆开组合数,再往下推下去:

{nm}=1m!mi=0(1)i(mi)(mi)n=mi=0(1)i(mi)ni!(mi)!

性质

mn=min(n,m)i=0(mi){ni}i!

从组合意义解释:

  • 等式左边的 mn 表示将 n 个不同的小球扔到 m 个不同的盒子里,盒子可以为空的方案数。
  • 等式右边先枚举非空的盒子个数 i(注意非空盒子个数不能大过总盒子数,也不能大过总球数,故 i 的枚举上界为 min(n,m)),再从这 m 个盒子中选出这 i 个盒子,然后把 n 个球扔到这 i 个盒子里,不能留空,最后再乘上 i!,因为 {ni} 的定义中盒子是相同的,但现在盒子是不同的。

事实上,i 的枚举上界是 nm 都可以,因为当 i>min(n,m) 时,(mi){ni} 必有一个为 0

再往下推下去还能跟下降幂扯上关系:

mn=min(n,m)i=0(mi){ni}i!=ni=0{ni}mi_

第二类斯特林数·行

给定 n,对于所有的 i[0,n],求出 {ni}

注意到上面通项公式有 {nm}=mi=0(1)i(mi)ni!(mi)!,那么我们直接设 Ai=(1)ii!Bi=ini!,然后多项式相乘 A×B 即得答案。

第二类斯特林数·列

给定 n,k,对于所有的 i[0,n],求出 {ik}

根据第二类斯特林数的递推式:

{nm}={n1m1}+m{n1m}

Fk(x)=i=0{ik}xi,那么:

Fk(x)=i=0{ik}xi=i=1{ik}xi=i=1({i1k1}+k{i1k})xi=i=1{i1k1}xi+i=1k{i1k}xi=i=1{ik1}xi+1+i=0k{ik}xi+1=xFk1(x)+kxFk(x)

解得 Fk(x)=x1kxFk1(x)

容易得到边界 F0(x)=1,那么:

Fk(x)=x1kxFk1(x)==xkki=1(1ix)

分治 NTT 求分母,然后再求逆即可。时间复杂度 O(nlog2n)

当然还有时间复杂度为 O(nlogn) 的更优秀做法,实现方法和第一类斯特林数·列类似。

第一类斯特林数

第一类斯特林数 [nm] 表示将 n 个不同的球划分为 k 个互不区分且不能为空的轮换的方案数。

轮换可以理解为环,旋转后相同的轮换互不区分,顺时针和逆时针的轮换需要区分(如 [A,B,C,D][D,C,B,A])。

递推公式

[n0]=|n=0|[nm]=[n1m1]+(n1)[n1m]

证明:从组合意义证明,我们考虑前 n1 个球已经分好了,现在插入第 n 个球。若前面的球组成了 m1 个轮换,那么这个球就得自己组成一个轮换;若前面的球已经组成了 m 个轮换,那么这个球可以跟在前 n1 个球的任意一个球后面。

第一类斯特林数没有实用的通项公式。

第一类斯特林数·行

结论:[ni] 的一般生成函数(OGF)为 x¯n

证明:使用数学归纳法。

x¯n+1=(x+n)x¯n=(x+n)ni=0[ni]xi=ni=0([ni1]+n[ni])xi=ni=0[n+1i]xi

于是我们求出 x¯n 即可,x¯n=n1i=0(x+i)

直接分治 NTT 是 O(nlog2n) 的,不够优秀。

考虑倍增:假设我们已经求出了 x¯n,现在要求 x¯2n

f(x)=x¯n,那么 x¯2n=f(x)f(x+n)。现在问题变为了:已经知道了 f(x),如何求 f(x+n)

我们直接暴力展开就好:

f(x+n)=ni=0fi(x+n)i=ni=0fiij=0(ij)nijxj=ni=0fiij=0i!j!(ij)!nijxj=nj=01j!xjni=jfii!×nij(ij)!

那么就可以卷积做了。

于是从 x¯n 推到 x¯2n 需要先 O(nlogn) 求出 f(x+n),再把 f(x)f(x+n) 相乘 O(nlogn) 得到 x¯2n

于是总时间复杂度为 O(nlogn)

第一类斯特林数·列

待填坑……

其他

自然数幂求和

Sk(n)=ni=0ik

1. n 固定,询问 k=0K 时的答案。

算法特点:时间复杂度 O(KlogK),需要模数能支持 NTT。

我们求出一个与 Sk(n) 有关的生成函数:

Kk=0Sk(n)1k!xk=Kk=0ni=0ik1k!xk=ni=0Kk=0(ix)kk!

注意到 ex 的泰勒展开为:ex=1+x1!+x22!+,故原式为:

=ni=0eix(modxK+1)

注意到 11x=1+x+x2+,有 1+x+x2++xn=1xn+11x

那么原式即为:

=ni=0(ex)i(modxK+1)=1e(n+1)x1ex(modxK+1)=e(n+1)x1ex1(modxK+1)=(n+1)x1!+(n+1)2x22!+(n+1)3x33!+x1!+x22!+x33!+(modxK+1)=(n+1)+(n+1)22!x+(n+1)33!x2+1+12!x+13!x2+(modxK+1)=(n+1)+(n+1)22!x++(n+1)K+1(K+1)!xK1+12!x++1(K+1)!xK

多项式求逆即可。

最后得到的系数记得乘上个 k! 才是 Sk(n)

时间复杂度 O(KlogK)

听说这玩意叫伯努利数?

2. 对于特定的 n,k

算法特点:时间复杂度近似 O(k),需要模数能支持求逆。

首先证明 Sk(n) 是关于 nk+1 次多项式:

考虑序列 a,其中 an=Sk(n)=ni=1ik

那么序列 a 的一阶差分序列 bn=an+1an=n+1i=1ikni=1ik=(n+1)k,是一个关于 nk 次多项式。

那么序列 b 就是一个 k 阶等差数列,那么序列 a 的一阶差分序列是一个 k 阶等差数列,那么序列 a 是一个 k+1 阶等差数列,所以 an 的通项公式是一个关于 nk+1 次多项式。

证毕。

但是我们不知道这个 k+1 多项式到底长啥样,而又注意到我们只需要求代入 n 时的多项式的值,所以考虑拉格朗日插值。

又有一个好处就是我们要代入的 k+2 个点可以自己选。

我们考虑代入点集 {(1,Sk(1)),(2,Sk(2)),,(k+2,Sk(k+2))}

那么我们就是要求出:

f(n)=k+2i=1Sk(i)jinxjxixj=k+2i=1Sk(i)jinjij

先观察右边的 jinjij

  • 对于分母,我们可以 O(k) 预处理出 prei=ij=1(nj)sufi=nj=i(nj)
  • 对于分子,我们可以 O(k) 预处理出阶乘 faci=i! 和它们的逆元 invi=1faci

那么 jinjij=prei1sufi+1(1)k+2ifacifack+2i=(1)k+2iprei1sufi+1inviinvk+2i

现在的问题就是如何对于每一个 i[1,k+2]Z 求出 Sk(i)。也就是如何对于每一个 i 求出 ik,然后求 Sk(i) 时只需求一遍前缀和即可。

如果直接暴力每次做一遍快速幂的话,时间复杂度为 O(klogk)

注意到 ik 为完全积性函数,所以我们直接线性筛即可。

那么此时只需对所有 k+2 的质数 ppk。不妨设 k 的质数个数为 π(k),那么时间复杂度为 O(π(k)logk)

又由于 π(k)kln(k)ln(k)log(k),故时间复杂度近似为 O(k)。(实测当 k=106π(k)logk1.5×106)。

3. 使用第二类斯特林数

算法特点:不需要模数支持取逆。

根据第二类斯特林数的性质:

mn=ni=0(mi){ni}i!=ni=0{ni}mi_

于是:

ni=0ik=ni=0kj=0{kj}ij_=kj=0{kj}ni=0ij_=kj=0{kj}(n+1)j+1_j+1

最后一步证明可以用二项式反演:ni=0ij_=j!ni=0(ij)=j!(n+1j+1)=(n+1)j+1_j+1

注意这里看上去除了个 j+1,但我们不需要在模意义下求逆,因为 nj+1,nj+1,,n+1j+1 个连续自然数肯定恰好有一个是 j+1 的倍数。

posted @   ez_lcw  阅读(137)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示