OI 中的多项式(或许完工?)
OI 中的多项式
目前已有知识点:
拉格朗日插值
模板
给定
个点 ,要求求出一个多项式函数 ,满足 的图像经过这 个点,并且 的度为 。给出一个 ,求 。(from Luogu P4781)
一个很朴素的办法就是直接列出方程组,然后用高斯消元求解。这样的时间复杂度是
设拉格朗日的基本多项式为
那么会发现对于一个
有了这个基本多项式,那么可以就构造出函数
容易发现,这个函数一定是满足题目中给出的
由于题目让我们求
快速傅里叶变换 FFT
前置知识
复数
复数
复平面是一个笛卡尔平面,有两条坐标轴,横轴是实部,纵轴是虚部。那么根据复数的形式可知,复数可以用复平面上的一个向量
复数的模
复数运算
加减法
加减法很好理解,实部和虚部对应相加即可。
乘法
类似二项式乘法的计算方法。
看一下在复平面上的意义。发现
欧拉公式
单位根
复数域下,满足
显然这样的
可以发现,这
本原单位根
代数上的不好理解,就不提了。复平面上辐角最小的单位根就叫做本原单位根。
将
关于本原单位根,有一个很重要的性质:
设
关于这两个式子的证明,可以画出复平面过后然后用旋转的想法去证明,这里不再给出(其实是懒)。
离散傅里叶变换 DFT
考虑两个多项式做乘法,如果直接用系数表示法的话显然时间复杂度是
将系数表示法转化为点值表示法的变换叫做 离散傅里叶变换(DFT),将点值表示法转化为系数表示法的变换叫做 离散傅里叶逆变换(IDFT)。
将一个
考虑构造出一个长度为
这里的
快速傅里叶变换 FFT
将
将后面那个求和式中的最后一个
假设:
那么有:
如果知道了
在前置知识中提到了关于本原单位根的两个公式:
那么根据第二个公式,启发我们只计算
设
那么根据第一个式子可以将这个式子化成:
然后对于后
用第二个式子可以化成:
然后效仿前一个的推法:
会发现求
离散傅里叶逆变换 IDFT
目前已知了一个多项式经过 DFT 后变成的点值表达式,即上面所说的
要求原系数表达式数列
这里直接给出结论(不会证):
如果直接求解的话仍然是
快速傅里叶逆变换 IFFT
会发现求解的这个式子和 FFT 是高度一致的。因为
这样,我们得到了一个可以
蝶形变换
会发现分治的过程可以用迭代的方式代替,这样就省去了动态开空间的时间。
具体做法就是先算出每个位置的值在分治到叶子节点的时候的位置,然后换到对应位置后直接从分治树的底端向上迭代进行计算。
for (int i = 1; i < lim; ++i)
rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (tim - 1));
代码结合例题给出。
例题
模板
给定多项式
,求 。(from Luogu P3803)
值得一说的是,这道题在之前递归做法因为常数过大是被卡了的,但是现在可以比较轻松跑过去了。
模板(高精乘)
给定
,求 ( )。(from Luogu P1919)
显然正常的高精度乘法是
需要注意最后可能某一位的系数会大于
快速数论变换 NTT
前置知识
原根
如果一个数
存在一个 ,满足 ,且 在模 下的阶等于 ,那么称 是 的原根。
这个定义并不好理解,需要用到一些群论的知识。但是这个原根具有很好的性质:
关于原根的定义了解到这里就足够理解 NTT 了。
NTT
FFT 中的所有系数都需要用 double
来表示,因此计算速度会很慢,并且还会丢失精度。所以就有一种叫做 NTT 的算法可以更高效地解决多项式乘法的问题。
考虑将答案对一个数
也就是说可以将
单位根的两个重要性质:
因此只需要将 FFT 的过程中使用到的单位根换成原根即可。
例题
给定多项式
,求 。(from Luogu P3803)
多项式ln
前置知识:
这里给出多项式求导和积分的式子:
复合函数求导法则:
多项式 ln
给定多项式
,求 满足 。(from Luogu P4725)
对两侧求导,得到
多项式牛顿迭代
有多项式
可以采用倍增的方式,假设已经求得了
容易发现有
推出:
多项式求逆
给定多项式
,求 满足 。(from Luogu P4238)
转化一下就是求
设
当
对于时间复杂度,有递推式
多项式开根
给定多项式
,求 满足 。(from Luogu P5205)
即
与多项式求逆做法相同,设
除法使用多项式求逆即可。
对于
时间复杂度同样是
多项式 exp
给定多项式
,求 满足 。(from Luogu P4726)
对两侧取
还是设
需要使用多项式 ln。
对于
时间复杂度仍然是
生成函数
前置知识: 数列
普通生成函数
定义
定义一个序列
如果
如果
的普通生成函数是 。 的普通生成函数是 。 的普通生成函数是 。
可以理解成为
运算
加减法:
乘法(卷积):
其实卷积就是多项式乘法。
封闭形式
如果直接带着这么多求和号进行运算会非常麻烦,因此可以用一种特殊的办法来表示普通生成函数。
以
解得:
这就称为
等比数列
指数生成函数
定义
序列
运算
加减法:
乘法(卷积):
封闭形式
序列
序列
例题
有
堆糖,每一堆糖有 个,你至少需要拿走 个糖,并且最多拿走 个糖,求你有多少种拿法(所有数据小于 )。
如果将每堆糖的方案表示成一个序列(下标表示取的个数,对应位置上的数表示这样取的方案数),那么可以得知第
由卷积的定义可以得知最后的方案数就是将每一堆糖的普通生成函数卷积起来就行了,即
由于数据范围很小,因此可以直接分治乘起来,或者用 NTT 或 FFT 计算。
有
五个数,要求组成一个 位数,每位上的数字可以相等,并且要求 的个数都是偶数个,问方案数。
延续上面的思路,用指数生成函数表示每一个数的方案:
为 为
那么总的方案的指数生成函数就是这五个值卷起来的结果:
将这个式子从封闭形式转回来得到通项公式:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步