我们已经知道了可以使用FFT和NTT在
O(nlogn)的时间内计算多项式乘法,那对于其它的运算呢?
首先,我们需要知道多项式逆元这个根本性的问题。
多项式求逆
考虑两个多项式
A(x),B(x),若A(x)B(x)≡1(mod xn),那么我们称
B(x)是A(x)mod xn意义下的逆元,即它们乘积的前
n项只有常数项为1,其它都是0.
那么我们如何计算逆元呢?考虑如果我们已经计算出了
A(x)C(x)≡1(mod xn),那么我们能不能推导出满足
A(x)B(x)≡1(mod x2n)的多项式
B(x)呢?
首先将两式相减,可以得到
A(x)(B(x)−C(x))≡0(mod xn)
由于等式左边多项式的前
n项系数都是0,可以把这个玩意儿平方:
A2(x)B2(x)+A2(x)C2(x)−2A2(x)B(x)C(x)≡0(mod x2n)
又由于
A(x)B(x)≡1(mod x2n),带入可以得到:
2A(x)C(x)−A2(x)C2(x)≡1(mod x2n)
提取多项式
A(x):
A(x)(2C(x)−A(x)C2(x))≡1(mod x2n)
即
B(x)=2C(x)−A(x)C2(x)。
于是我们会发现一个多项式是否有逆元完全取决于该多项式的常数项是否有逆元。由于这个算法每次可以将问题规模减半,总的时间复杂度就是
T(n)=T(2n)+O(nlogn)=O(nlogn)
例题 洛谷3711 仓鼠的数学题
题目链接
首先可以想到使用伯努利数来化简算式。于是就有
f(n)=k=0∑nSk(x)ak=1+k=0∑nakk+11i=0∑k(−1)i(ik+1)Bixk+1−i
最开始有个1是因为题目中把
00也算为1.然后我们考虑继续化简:
f(n)−1=i=0∑ni!(−1)ik=i∑n(k+1−i)!akBixk+1−ik!
由于我们要求的是多项式,考虑枚举x的指数:
f(n)−1=i=1∑n+1i!xik=0∑n+1−ik!(−1)kBk(i+k−1)!
然后就是很经典的翻转卷积模型了。
令A(k)=k!(−1)kBk