多项式最基础的操作
Posted cmxrynp
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多项式最基础的操作相关的知识,希望对你有一定的参考价值。
多项式乘法
略
时间复杂度(O(n log n))
const int P = 998244353;
inline int Pow(ll x, int y=P-2){
ll ass=1;
for(; y; y>>=1, x=x*x%P) if(y&1) ass=ass*x%P;
return ass;
}
inline int Mod(int x){ return x<P?x:x-P;}
inline void NTT(int *f, int g){
for(int i=0, j=0; i<p; ++i){
if(i>j) swap(f[i], f[j]);
for(int k=p>>1; (j^=k)<k; k>>=1);
}
for(int i=1; i<p; i<<=1){
int w0=(g==1?Pow(3, (P-1)/i/2):Pow(Pow(3, (P-1)/i/2)));
for(int j=0; j<p; j+=i<<1){
int w=1;
for(int k=j; k<j+i; ++k){
int t=(ll)w*f[k+i]%P;
f[k+i]=Mod(P+f[k]-t);
f[k]=Mod(f[k]+t);
w=(ll)w*w0%P;
}
}
}
if(g==-1) for(int i=0, I=Pow(p); i<p; ++i) f[i]=(ll)f[i]*I%P;
}
..............
多项式求逆
给定多项式(A(x)),求(A^{-1}(x))满足[A(x)A^{-1}(x)equiv 1pmod{x^n}]
其中(pmod{x^n})即为舍去次数(ge n)的项,只保留(0)到(n-1)次项
考虑倍增
(n=1)时只有常数项,答案可以直接快速幂求出
假设当前已经求出(pmod{x^{lceil frac{n}{2} ceil}})意义下的(A(x))的逆元(B'(x)),满足[A(x)B'(x)equiv 1pmod{x^{lceil frac{n}{2} ceil}}]
需要求(B(x))满足[A(x)B(x)equiv 1pmod{x^n}]
两式相减得[A(x)(B(x)-B'(x))equiv 0pmod{x^{lceil frac{n}{2} ceil}}]
即[B(x)-B'(x)equiv0pmod{x^{lceil frac{n}{2} ceil}}]
平方得[B^2(x)-2B(x)B'(x)+B'^2(x)equiv0pmod{x^n}]
由于一个多项式平方之后,次数(<n)的项至少是由原先一个次数(<lceil frac{n}{2} ceil)的项乘上其他项得到的,所以这个结果的(0)到(n-1)次系数仍然是(0),可以变成(pmod{x^n})
同乘(A(x))得[B(x)-2B'(x)+A(x)B'^2(x)equiv0pmod{x^n}]
即[B(x)equiv B'(x)(2-A(x)B'(x))pmod{x^n}]
其中多项式乘法可以使用快速傅里叶变换加速
时间复杂度[T(n)=T(frac{n}{2})+O(n log n)=O(n log n)]
inline void polyinv(int n, int *a, int *b){
if(n==1) return (void)(b[0]=Pow(a[0]));
polyinv((n+1)/2, a, b);
static int tmp[N];
for(p=1; p<n*2-1; p<<=1);
memcpy(tmp, a, n<<2), memset(tmp+n, 0, p-n<<2);
NTT(tmp, 1), NTT(b, 1);
for(int i=0; i<p; ++i) b[i]=(2-(ll)b[i]*tmp[i]%P+P)*b[i]%P;
NTT(b, -1);
memset(b+n, 0, p-n<<2);
}
(未完)
以上是关于多项式最基础的操作的主要内容,如果未能解决你的问题,请参考以下文章
[Go] 通过 17 个简短代码片段,切底弄懂 channel 基础