多项式专题
多项式
点值表示法和系数表示法
代数基本定理: 一个\(n-1\)次多项式在复数域上有且只有\(n-1\)个根
多项式有点值表示法和系数表示法两种
- 系数表示法:\(A(x)=\sum_{i=0}^{n-1}a_ix^i\)
- 点值表示法:\(y_i=\sum_{j=0}^{n-1}a_jx_i^j\)
定理: 一个n-1次多项式在n个不同点的取值唯一确定了该多项式
证明:
考虑反证法,假设命题不成立,则存在两个\(n-1\)次多项式\(A(x)\)和\(B(x)\)且\(\forall i\in[0,n-1],A(x_i)=B(x_i)\)
令\(C(x)=A(x)-B(x)\),那么\(C(x)\)至多是一个\(n-1\)次多项式且\(\forall i\in[0,n-1],C(x_i)=0\)
也就是\(C(x)\)有\(n\)个根,与代数基本定理不符合
已知多项式点值表示法求系数表示法的过程被称为插值
拉格朗日插值
问题
已知平面上\(n+1\)个点,有一条过\(n+1\)个点的曲线(多项式)
,求该在该曲线某一位置的取值
法1 高斯消元
略
法2 拉格朗日插值
已知\(n+1\)个点的坐标为\(x_i,y_i\),函数在\(x=k\)时的取值
证明
同样,\(n\)个点的坐标为\(x_i,y_i\)
由\(CRT\)可知
由于\(x-x_j\) 与 \(x-x_j-(x-x_i)\) 在模多项式 \(x-x_i\) 的意义下是等价的
即
\(x-x_j\equiv x_i-x_j\pmod{(x-x_i)}\)
所以有
\(m^{-1}_{i}=\prod_{i\neq j}\frac 1{x_i-x_j}\)
所以有
所以在模意义下\(f(x)\)就是唯一的,即
求某一点处的函数值\(O(n^2)\)
求出整个多项式\(O(n^3)\)
在x取值连续的时候的做法
由于\(x_i\)连续,所以将其换为\(i\)
分母维护前缀积和后缀积
分子维护阶乘
时间复杂度:
求函数值\(O(n)\)
求多项式\(O(n^3)\)
由此,我们发现普通的拉格朗日插值在增减坐标时需要全部重新计算
并且对求多项式并没有任何的优化
所以考虑进行进一步的优化
重心拉格朗日插值法
设
则
那么这样有什么用呢?
对于\(\lceil求出次数不超过n的多项式\rfloor\)问题,枚举每一个\(x_i\),计算每一个\(\frac{g(k)}{k-x_i}\),这样得到的就是\(x_i\)对应的多项式,然后我们将所求出来的\(n+1\)个多项式的系数相加即可以得到我们所想要的多项式
举个例子
对于多项式\(f(k)=a_0+a_1k+a_2k^2\)
所以有
还有系数\(\sum_{i=0}^n\frac{t_iy_i}{k-x_i}\),计算出来分别为\(\frac92,-20,\frac {37}2\)
将系数乘在上面的式子中
将三个式子系数相加
即可得到\(f(k)=3k^2+2k+4\)
考虑一下这个过程,由于所除的\(k-x_i\)为二项式,时间复杂度为\(O(n)\),枚举\(n\)项,所得的总时间复杂度为\(O(n^2)\)
此外,如果我们想要新加入一个点\((x,y)\),我们只需增加一次对\(i=n+1\)枚举,给\(g(k)\)乘上\(k-x\),同时让每一个\(t_i\)除以\(x_i-x\),这个过程的复杂度为\(O(n)\),因此如果我们想要插\(n\)个点进来,复杂度就为\(O(n^2)\)
所以重心拉格朗日插值,在有关多项式求函数值、求多项式系数上完全优于高斯消元
单位根
\(\omega_n=cos\frac{2\pi}{n}+isin\frac{2\pi}{n}\)
\(\omega_n^k=cos\frac{2k\pi}{n}+isin\frac{2k\pi}{n}\)
单位根的性质
\(1.\omega_n^k=\omega_{rn}^{rk}\)
\(2.(\omega_n^k)^n=1\)
\(3.\omega_{2n}^k=-\omega_{2n}^{k+n}\)
\(4.\omega_n^a\times \omega_n^b=\omega_n^{ab}\)
\(5.\omega^0_n=\omega^n_n=1\)
为什么我们需要傅里叶变换
多项式有两种表示方法——系数表示法和点值表示法
系数表示法就是经典的
我们在重心拉格朗日插值法中,已知任意\(n+1\)个点的坐标,便可以\(O(n^2)\)地求出一个多项式的各项系数
这也说明,这\(n+1\)个点所对应的多项式是唯一确定的,这样用点和坐标表示多项式的方法叫做点值表示法
对于多项式,\(f(x),\deg f(x)=n\)它写成这个样子
那么它有什么用呢?
已知两个多项式\(f(x),g(x)\),有\(\deg f(x)=n,\deg g(x)=m\),有\(\deg f(x)g(x)=n+m\),于是我们可以找\(n+m+1\)个点,分别带入\(f(x),g(x)\)
我们发现这个过程是\(O(n)\)的,很优秀,是吧\(\cdots\)
是吗?
如果只是随机取点,点值表示转成系数表示的复杂度暂时只能做到\(O(n^2)\),这是我们无法接受的
于是我们就需要\(FFT\)和它的单位根了
那么\(FFT\)完成的操作就是:
- 把已知的一个多项式转化成对应的点值表示;
- 把已知的点值表示转换成对应的多项式。
复杂度都是 \(O(n\log n)\)
快速傅里叶变换
Part 1 DFT
\(f(x)=(a_0+a_2x^2+a_4x^4+\cdot\cdot\cdot+a_{n-2}x^{n-2})+(a_1x+a_3x^3+a_5x^5+\cdot\cdot\cdot+a_{n-1}x^{n-1})\)
设\(f_1(x)=a_0+a_2x^1+a_4x^2+\cdot\cdot\cdot+a_{n-2}x^\frac{n-2}{2}\)
\(f_2(x)=x(a_0+a_2x^1+a_4x^2+\cdot\cdot\cdot+a_{n-2}x^\frac{n-2}{2})\)
则有
\(f(x)=f_1(x^2)+f_2(x^2)\)
将\(x=\omega^k_n\) 带入
\(f(\omega^k_n)=f1(\omega^{2k}_n)+\omega^k_nf_2(\omega^{2k}_n)\)
\(=f_1(\omega^k_{\frac n2})+\omega^k_nf_2(\omega^k_\frac n2)\)
将\(x=\omega^{k+\frac n2}_n\)得
这也就意味着,如果可以求出\(f_1(\omega^{k}_\frac n2)\)与\(f_2(\omega^{k}_\frac n2)\),我们即可以求出\(f(\omega^{k+\frac n2}_n)\)与\(f(\omega^{k}_n)\)
多项式最终会递归到只有一个常数项
这样就用\(O(nlogn)\)的复杂度将系数表示转成了点值表示
将点值表示后的两个多项式相乘得到它们乘积的点值表示
Part 2 IDFT
考虑如何将点值表示转成系数表示
令\((y_0,y_1,y_2,\cdot\cdot\cdot,y_{n-1})\)是\((a_0,a_1,a_2,\cdot\cdot\cdot,a_{n-1})\)的点值表示
设另一个向量(复数)为
\(c_k=\sum_{i=0}^{n-1}y_i(w_n^{-k})^i\)
即多项式\(A(x)=y_0+y_1x+y_2x^2+\cdot\cdot\cdot+y_{n-1}x^{n-1}\)在\(\omega_n^0,\omega_n^{-1},\omega_n^{-2},\cdot\cdot\cdot,\omega_n^{-(n-1)}\)处的点值表示
其中\(y_i=f(\omega_n^i)\)
式子:
设\(S(x)=\sum_{i=0}^{n-1}x^i\)
将\(x=\omega^k_n\)带入得
一式\(S(\omega_n^k)=\sum_{i=0}^{n-1}\omega_n^{ik}\)
二式\(\omega_n^kS(\omega_n^k)=\sum_{i=1}^{n}\omega_n^{ik}\)
二式相减得
当\(k\neq0 ,S(\omega_n^k)=0\)
当\(k=0,S(\omega_n^0)=n\)
考虑刚才推的式子
当\(j\neq k\)时,值为 \(0\)
当\(j=k\)时,值为 \(n\)
因此有
于是我们得到了点值与系数的关系式了
由
将 DFT 中的单位根改为\(\omega_n^{-k}\),求解出\(na_k\)后,除以\(n\) 即为所要求的系数
FFT的优化方法
三次变两次
考虑下面这个式子
令\(a=f(x),b=g(x)\)
我们一次 DFT 计算出\(f^2(x)\),它的虚部即为\(f(x)g(x)\)
在 IDFT 一次就可以得到答案
蝴蝶变换
递归的常数太大
不失一般性的,设\(k\)为偶数。对于初始是
的序列,在递归的第一层会将其拆分为
和
两部分。
也就是说对于任意的\(\omega_n^i\),若 \(i\) 在二进制下最后一位为\(0\) 则 \(\omega_n^i\) 会被分配到前半部分,否则会被分配到后半部分。
换言之,当前 \(i\) 在二进制下的倒数第 \(j\) 位决定了它在当前长度为 \(2^{k-j+1}\) 的区间中是被分配到长度为 \(2^{k-j}\) 的前半部分还是长度为 \(2^{k-j}\) 的后半部分。
可以发现 \(\omega_n^i\) 在最终的序列中的位置下标相当于 \(i\) 二进制下翻转得到的数
然后就可以愉快地递推了
NTT快速数论变换
我们为什么需要NTT
\(FFT\)在计算过程中有着大量的精度丢失,导致答案计算并不准确,这是我们所不能接受的
参考对除法的处理,我们考虑将\(FFT\)带到模意义下
于是我们要考虑如何将\(FFT\)的单位根改到模意义下,很自然地想到了原根,为什么?
考虑原根的定义
\(在模m的意义下,\exist a \in N^*,使得a^1,a^2,a^3,\cdot\cdot\cdot,a^{\varphi(m)}两两不同\)
取模的过程很像是一个循环,这与我们单位根在复平面上绕圈的过程相仿
我们知道单位根有如下的性质
\(1.\omega_n^k=\omega_{rn}^{rk}\)
\(2.(\omega_n^k)^n=1\)
\(3.\omega_{2n}^k=-\omega_{2n}^{k+n}\)
\(4.\omega_n^a\times \omega_n^b=\omega_n^{ab}\)
\(5.\omega^0_n=\omega^n_n=1\)
那么只有当原根与单位根性质完全相同时,我们才可以等价替换,定义
我们来检验一下
由费马小定理
由于原根互不相同和费马小定理,有
所以
\(4.5.\)均采用类似上面的证明方法,由此我们证明了原根可以完美替代单位根,这就是\(NTT\)了
注意只有当\(n\mid(m-1)\)的时候\(NTT\)才可以正确地运行
\(n\)总是\(2\)的整数次方,所以\(m-1\)必然可以写成\(2^rd+1\)的形式
常见的\(NTT\)模数:
469762049
998244353
1004535809
任意模数NTT
如果模数不是\(NTT\)模数该怎么办呢?
有一个想法是我们可以先用\(NTT\)模数算出系数,然后再对题目要求的模数取模
但是如果题目的系数大于\(NTT\)模数,那我们就无法计算出准确的系数了
如\(LuoguP4245 【模板】任意模数多项式乘法\),这道题,其极限情况可以达到\(10^9\times 10^9\times 10^5=10^{23}\),直接\(NTT\)必然寄掉
既然一个模数不够用,那我们直接参考哈希,将模数扩展成三个,只需要取三个模数,使其乘积大于极限情况,最后再用中国剩余定理合并就好了
注意在中国剩余定理时会爆long long,所以可以全部定义成__int128
分治NTT
问题
给定序列 \(g_{1\dots n - 1}\),求序列 \(f_{0\dots n - 1}\)。
其中 \(f_i=\sum_{j=1}^if_{i-j}g_j\),边界为 \(f_0=1\)。
答案对 \(998244353\) 取模
题解
直接暴力\(O(n^2)\)
如果直接\(NTT\),复杂度为\(O(n^2\log n)\)
显然这是一个比暴力还要劣的解
所以我们考虑\(CDQ\)分治
要求区间\([l,r]\)的答案,假设我们已经求出了区间\([l,mid]\),现在考虑右半边的答案,令\(x\in [mid+1,r]\),那么考虑左子区间对它的贡献为
这是一个卷积的形式,可以利用\(NTT\)计算
复杂度为\(O(n\log^2 n)\)
莫比乌斯变换与莫比乌斯反演
莫比乌斯变换
莫比乌斯反演
证明
由
可得
证毕。
合并卷积
定义
称 \(h\) 是 \(f\) 和 \(g\) 的合并卷积。
设 \(\hat h(S)\) 是 \(h(S)\) 的莫比乌斯变换,则
这启发我们计算 \(f\) 和 \(g\) 的合并卷积时,可以先将 \(f\) 和 \(g\) 分别做莫比乌斯变换,然后相乘,得到 \(h\) 的莫比乌斯变换 \(\hat h\),再对 \(\hat h\) 做莫比乌斯反演,即得到 \(f\) 和 \(g\) 的合并卷积 \(h\)
快速莫比乌斯变换
快速莫比乌斯变换FMT
要对所有的\(S\),求
定义
那么有 \(\hat f(S,0)=f(S),\hat f(S,|S|)=f(\varnothing)\)。
设集合 \(S\cap \{i\}=\varnothing\),
那么
因为
\(S\cap \{i\}=\varnothing\),所以 \(\hat f(S,i)=\hat f(S,i-1)\)
\(\hat f(S,i)\)表示 \(\{i+1,i+2,\dots,n\}\) 一定含于 \(T\),并且一定没有选 \(i\),
\(\hat f(S\cup\{i\},i-1)\) 表示 ${i+1,i+2,\dots,n} $一定含于 \(T\),并且一定选了 \(i\),
那么由加法原理即可知
那么我们递推 \(n\) 轮,即可求得 \(\hat f(S)\)。
时间复杂度 \(O(n2^n)\)。
void FMT(int *f)
{
for(int i=0;i<n;++i)
for(int j=0;j<(1<<n);++j)
if(j&(1<<i)) f[j]+=f[j^(1<<i)];
}
这个过程相当于高维前缀和
IFMT快速莫比乌斯反演
跟FMT一样,不断递推,不过变成了减法。
void IFMT(int *f)
{
for(int i=0;i<n;++i)
for(int j=0;j<(1<<n);++j)
if(j&(1<<i)) f[j]-=f[j^(1<<i)];
}
这个过程相当于高维差分
子集卷积
由于
因而可以将原集合按照元素个数分组,做\(FMT\),然后再\(n^2\)次结合,并做\(IFMT\),最终将结果累计
复杂度\(O(2^nn^2)\)
快速沃尔什变换
与/或卷积
- 或卷积:\(c_i=\sum_{j}\sum_{k}[j~or~k=i]a_jb_k\)
- 与卷积:\(c_i=\sum_{j}\sum_{k}[j~and~k=i]a_jb_k\)
考虑如何求\(a\)和\(b\)的或卷积:
引理:
若\(j,k\subseteq i\),则\(j~or~k\subseteq i\),逆命题同样成立
若\(j,k\supseteq i\),则\(j~and~k\supseteq i\),逆命题同样成立
设\(a,b,c\)的高维前缀和分别为\(A,B,C\)
现在考虑已知\(C\)求\(c\),本质上是一个反演
注意到
于是
因而做两遍高维前缀和再反推回去即可,复杂度\(O(2^nn)\)
与卷积即改为高维后缀和
inline void FWT_and(ll *a,ll t,int limit){//FWT:t=1;IFWT:t=-1
for(int mid=1;mid<limit;mid=mid<<1){
int n=mid<<1;
for(int j=0;j<limit;j+=n){
for(int k=0;k<mid;++k){
a[j+k]+=t*a[j+k+mid]%mod;
Mod(a[j+k]);
}
}
}
return ;
}
inline void FWT_or(ll *a,ll t,int limit){//FWT:t=1;IFWT:t=-1
for(int mid=1;mid<limit;mid=mid<<1){
int n=mid<<1;
for(int j=0;j<limit;j+=n){
for(int k=0;k<mid;++k){
a[j+k+mid]+=t*a[j+k]%mod;
Mod(a[j+k+mid]);
}
}
}
return ;
}
异或卷积
快速沃尔什变换(FWT):
定义集合幂级数\(FWT(a)\),满足\(FWT(a)_i=\sum_{j=0}^{2^n-1}(-1)^{|i~and~j|}a_j\)
那么有:
时间复杂度\(O(2^nn)\)
\(FMT\)可以看作是\(FWT\)在解决或卷积,与卷积时的特例
inline void FWT_xor(ll *a,ll t,int limit){//FWT:t=1;IFWT:t=mpow(2,mod-2)
for(int mid=1;mid<limit;mid=mid<<1){
int n=mid<<1;
for(int j=0;j<limit;j+=n){
for(int k=0;k<mid;++k){
ll x=a[j+k],y=a[j+k+mid];
a[j+k]=t*(x+y)%mod;Mod(a[j+k]);
a[j+k+mid]=t*(x-y+mod)%mod;Mod(a[j+k+mid]);
}
}
}
return ;
}
多项式牛顿迭代
给定多项式\(g(x)\),求解关于多项式\(f(x)\)的方程
我们假设已经求出了\(f(x)\)前\(n\)项的多项式\(f_0(x)\),显然有
考虑\(g(f(x))\)在\(x\)处泰勒展开
我们来考虑一件事情
对于\((f(x)-f_0(x))^k\),当\(k\)大于等于\(2\)时,显然有结论
那么就有
递归计算即可
多项式 ln
已知一个多项式\(f(x)\),求下式中的多项式\(r(x)\)
解决这个问题之前,先介绍多项式求导和多项式积分
多项式求导
利用导数公式\(x^n=nx^{n-1},(kx)'=kx'\)即可
其中\(k\)是常数
多项式积分
利用公式
计算即可
回到原问题
因此\(f'(x)\)乘上\(f(x)\)的逆元,再积个分就是\(r(x)\)了
多项式exp
问题
已知一个多项式\(f(x)\),求\(r(x)\)
先对它两边\(\ln\)得
令\(g(r(x))=\ln(r(x))-f(x)\),则\(g(r(x))\equiv0\pmod{x^n}\),因此我们可以采用牛顿迭代法,假设我们已经求出了\(r(x)\)的前\(n\)项\(r_0(x)\),有
然后递归计算\(r(x)\)即可求出答案
多项式快速幂
给定\(f(x)\)与常数\(p\),求多项式\(r(x)\)使得
法1
直接快速幂套上多项式乘法,时间复杂度\(O(n\log n\log p)\)
法2
考虑到\(x=e^{\ln x}\),所以
于是我们可以考虑先计算\(\ln f(x)\),将它的各项系数乘\(p\)得到\(p\ln f(x)\),再做一个多项式\(\exp\)即可
复杂度\(O(n\log n)\)
多项式乘法的技巧
\(FFT/NTT\)可以快速求下面这个式子
如果要求的形式长下面这个样子
这不是我们想要的卷积形式,于是可以考虑将\(a\)翻转
由于\(n+1-j+i+j=n+i+1\)与\(j\)无关,所以我们将翻转后的\(a\)与原来的\(b\)做一下卷积,然后将得到\(d\)序列,有\(c_i=d_{n+i+1}\)
多项式求逆
问题
给定多项式\(f(x)\) ,求\(f^{-1}(x)\)
做法
首先,易知
假设已经求出\(f(x)\)在模\(x^{\lceil\frac n2 \rceil}\)意义下的逆元\(f_0^{-1}(x)\)。有:(均为模意义下)
因此
两边平方,变为模\(x^n\)意义下
同时乘\(f(x)\)并移项
递归计算即可
时间复杂度\(O(nlogn)\)
多项式除法(取模)
问题:
给定多项式\(f(x),g(x)\),求\(g(x)\)除\(f(x)\)的商\(Q(x)\)与余数\(R(x)\)
考虑构造系数翻转的变换
进行推导,设\(n=\deg f,m=\deg g\),两边乘上\(x^n\)并将\(x\)更换为\(\frac1x\)
此时我们发现,如果我们两边取模\(x^{n-m+1}\),就可以消除\(R^R(x)\)的影响,因为\(Q^R(x)\)的次数\(n-m<n-m+1\),所以取模并不会对\(Q^R(x)\)产生影响,所以可以求解\(Q(x)\),反带之后就可以求解\(R(x)\)
即
多项式开方
问题:
给定多项式\(g(x)\),求多项式\(f(x)\),满足
解法
假设已经求出了\(g(x)\)在模\(x^{\lceil\frac n2\rceil}\)意义下的平方根\(f_0(x)\)
则有
递归计算即可
特征方程
一个数列\(\lbrace x_i\rbrace\) 存在递推式\(x_{n+2}=c_1x_{n+1}+c_2x_{n}\)
设有\(r,s\),使得
那么
于是有
韦达定理构造方程得
这样解出\(x\)的两根即为\(s,r\),进而可以求解\(c_1,c_2\)
特征方程在一阶线性递推中的应用
设数列\(\lbrace a_i\rbrace\)的递推公式为
设
那么
将\(t\)解出代入上式,利用等比数列求和得出数列的通项公式
常系数齐次线性递推
问题
给定一个线性递推数列
的前\(k\)项 \(f_0\cdots f_{k-1}\)和其递推式\(f_n=\sum_{i=1}^ka_if_{n-i}\)的各项系数\(a_i\),求\(f_n\)
矩阵快速幂做法
我们构造它的初始矩阵为
加速矩阵为
由此,时间复杂度为\(O(k^3\log n)\)
瓶颈在于如何快速求出加速矩阵\(A^{n-k+1}\)
为了解决这个问题,我们可以引出常系数齐次线性递推
先介绍一些前置知识
特征值与特征向量
矩阵乘上列向量仍然是一个列向量
若对于矩阵\(A\),存在一个列向量\(\vec v\)和一个常数\(\lambda\),使得
那么称\(\vec v\)为矩阵\(A\)的特征向量,\(\lambda\)为矩阵\(A\)的特征值,上面那个方程称为矩阵\(A\)的特征方程
令\(\vec v\)为初始矩阵,\(A\)为加速矩阵,那么有方程
发现
又因为
将\(f_i\)全部换成\(f_1\)
那么有
我们设
写高级点
此时称\(\varphi(x)\)为矩阵\(A\)的特征多项式
它也可以这样表示
特征多项式
考虑当\(x=A\),有
即对于矩阵\(A\)的特征多项式\(\varphi(x)\),有\(\varphi(A)=0\),这被称为\(Cayley-Hamilton定理\)
常系数齐次线性递推
前置知识说完了,考虑我们原先的问题
如何快速求出\(A^{n-k+1}\)
我们将问题简化为求\(A^n\),这与上面那个问题在规模上是等价的
考虑多项式除法/取模
其中\(g(x),r(x)\)为两个多项式,此时我们可以利用前面学到的多项式取模求得\(r(x)\),但这有什么用呢?
将其改为矩阵的形式
由\(Cayley-Hamilton定理\)可知,\(\varphi(A)=0\)
那么有
由多项式取模的定义,\(\deg (r(x))< k\),复杂度有了保证
所以我们把原来的矩阵\(A\)带入求出的多项式\(r(x)\),设它为
我们在两边乘上\(\vec v\),然后推导
然后,终于做完了!
posted on 2022-08-05 08:34 star_road_xyz 阅读(231) 评论(0) 收藏 举报
浙公网安备 33010602011771号