[Notes][多项式]杂记 · 多项式算法—多项式求逆 多项式取模 多项式开根…

多项式

由若干个单项式相加组成的代数式叫做多项式
形如: f(x)=ni=0aixi f ( x ) = ∑ i = 0 n a i x i
deg f(x) deg ⁡   f ( x ) 称为 f f 的度,是 f ( x ) 最高次项的次数。

生成函数

形如 i=0aixi ∑ i = 0 ∞ a i x i
生成函数又称母函数,往往和多项式算法联系起来起到优化转移的作用

多项式算法

加减法

多项式加减法比较简单
f(x)=ni=0aixi f ( x ) = ∑ i = 0 n a i x i g(x)=ni=0bixi g ( x ) = ∑ i = 0 n b i x i

(f±g)(x)=ni=0(ai±bi)xi ( f ± g ) ( x ) = ∑ i = 0 n ( a i ± b i ) x i

代码实现也比较简单


乘法

多项式乘法是所有多项式算法的基础,也是生成函数的卷积运算

f(x)=ni=0aixi f ( x ) = ∑ i = 0 n a i x i g(x)=ni=0bixi g ( x ) = ∑ i = 0 n b i x i

(f×g)(x)=2ni=0ij=0aj×bijxi ( f × g ) ( x ) = ∑ i = 0 2 n ∑ j = 0 i a j × b i − j x i

朴素的多项式乘法是 O(n2) O ( n 2 ) 的,但FFT(快速傅里叶变换)运用复数根的特性可以在 O(nlogn) O ( n log ⁡ n ) 的复杂度内实现多项式的系数表达和点值表达的转化,运用点值表达实现 O(n) O ( n ) 的相乘,总复杂度就是 O(nlogn) O ( n log ⁡ n ) ,但是因为常数过大,往往小范围会使用暴力。

inline void FFT(E *a,int r){
  for(int i=0;i<n;i++) if(rev[i]>i) swap(a[rev[i]],a[i]);
  for(int i=1;i<n;i<<=1){
    E wn(cos(M_PI/i),r*sin(M_PI/i));
    for(int j=0;j<n;j+=(i<<1)){
      E w(1,0);
      for(int k=0;k<i;k++,w=w*wn){
    E x=a[j+k],y=w*a[j+k+i];
    a[j+k]=x+y; a[j+k+i]=x-y;
      }
    }
  }
  if(r==-1) for(int i=0;i<n;i++) a[i].real/=n;
}

运用生成函数的计数问题往往会对一个质数取模,如果这个质数可以表示成 k×2n+1 k × 2 n + 1 ,其中 k k 为奇数 n 大于多项式的度数,那么就可以用这个质数的原根代替复数根,实现多项式的系数对一个质数取模,这个算法就是NTT(快速数论变换),这种模数称为NTT模数。

inline void Pre(int n){
  num=n;
  int g=Pow(3,(P-1)/num);
  w[0][0]=w[1][0]=1; for(int i=1;i<num;i++) w[0][i]=1LL*w[0][i-1]*g%P;
  for(int i=1;i<num;i++) w[1][i]=w[0][num-i];
}

inline void NTT(int *a,int n,int r){
  for(int i=1;i<n;i++) if(rev[i]>i) swap(a[i],a[rev[i]]);
  for(int i=1;i<n;i<<=1)
    for(int j=0;j<n;j+=i<<1)
      for(int k=0;k<i;k++){
        int x=a[j+k],y=1LL*a[j+k+i]*w[r][num/(i<<1)*k]%P;
        a[j+k]=(x+y)%P; a[j+k+i]=(x+P-y)%P;
      }
  if(!r) for(int i=0,inv=Pow(n,P-2);i<n;i++) a[i]=1LL*a[i]*inv%P;
}

不过有些丧心病狂的题的模数不是NTT模数,这个时候需要CRT合并。


多项式求逆

比如BZOJ4555

最后会得到 f(x)=f(x)g(x)+1 f ( x ) =

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值