多项式
多项式在计算机中一般以数组方式储存,假设有一个多项式$f(x)$,并且$x^i$前面的系数为$a_i$,那么显然我们恰好可以用一个数组$a$来描述这个多项式, 多项式的系数$a_i$恰好存在数组$a$的第$i$项$a[i]$
多项式dft
在一般的多项式中,如果模数允许,乘法采取ntt来做,因为速度较快,多项式乘法是整个多项式体系的基石,他的常数如果太大,将影响到后面的所 有的多项式操作
多项式前期预处理
我们需要设置多项式最大长度,模数,原根,多项式最大长度的log,以及关键点reduce函数,传入一个-mod到mod之间的数x,返回x%mod,他比取模更快,然后是快速幂,在往后是复数i在模意义下的值,2i在模意义下的逆元,以及后面的逆元数组和他的初始化函数
1 | const int maxn=100005<<2,mod = 998244353,g=3;// const 能明显加速代码 |
dft
蝴蝶变化必须预处理出来,否则太慢,最前面的是蝴蝶变换r[i][j]
数组, 之后是ntt单位根wn数组和他的逆元数组。接着是ntt的数组的预处理函数以及ntt函数本体
1 | int allr[maxn<<1],*r[30],ntt_wn[30],ntt_revwn[30]; // 特别详细,没啥其他可说的 |
多项式拓展与对齐
为了后期代码可观性良好,以及少写一些奇怪的代码,poly_cpy(int*a,int n,int*b,int exn)
提供了多项式拷贝等操作,即将一个多项式拷贝到另外一个多项式,必须保证exn>=n ,即先将a[0…n-1]拷贝到b[0…n-1] 然后把b数组多余的部分清零。这里如果ab为同一个数组,就不必进行拷贝了。
1 | void poly_cpy(int*a,int n,int *b,int exn){// |
多项式乘法
为了防止常数问题,这里依旧采取最简单的方式,不让数组发生过多的拷贝,我们只实现a*=b
这一个步骤,不实现c=a*b
这种,很套路的乘法,先变为点指表示法 然后变为系数表示法即可
1 | void poly_mul(int*a,int na,int*b,int nb){ |
多项式求逆
若两个多项式$f$和$g$,求出$f*g$然后让系数对mod取模,多项式忽略高于$x^k$次的项后等于1,则$f$和$g$互逆
这个地方很难以理解,因为有两个取模,所以会让很多初学者感到困惑,只要注意两个模是不同的,一个是系数对mod取模,另一个是多项式整体对$x^k$取模,即可
整个算法采取牛顿迭代法来完成,很容易被数学归纳法证明,$f(x)*g(x)===1(x^k,mod)$,当k等于1的时候,非常好得出结果,显然那时候g(x)至少需要 1项,即常数项,大于常数项的部分无效的,这个很容易证明,这一项等于$f(x)$的常数项的逆元。然后我们来根据$f(x)*g(x)===1(x^k,mod)$推出$f(x)g(x)===1(x^2k,mod)$ 的结果,以下是推导过程,显然$g(x)=g(x)(2-f(x)*g(x))$,只要自己注意一下项数的变化即可,然后我们倍增即可得出答案时间复杂度$T(n)=T(n/2)+nlg(n)$ 根据主定理$T(n)=O(nlgn)$img
1 | void poly_inv(int*a,int n,int*b){ // // %(x^n) b(2-ab) |
多项式除法
除法会有剩余,所以有两个返回值。
对于一个n-1次多项式f(x) 定义F(x)=x^nf(1/x) 则有以下推导img 余数直接ntt暴力即可
1 | void poly_div(int*a,int na,int*b,int nb,int*c,int*d){ |
多项式取对数
img
于是求导、求逆、乘、积分即可完成
1 | void poly_der(int*a,int n,int*b){ // 微分求导 |
多项式求指数函数
大佬已将讲的很清楚了,用泰勒展开求的img
1 | void poly_exp(int*a,int n,int*b){//a[exn(n+n-1)] // 保证f(0)=0 b(1-ln(b)+f), |
多项式开根
递归边界改为二次剩余即可img
1 | void poly_sqrt(int*a,int n,int*b){//a[exn(n+n-1)] //保证a[0]=1, (b+a/b)/2 比上面那个好一些 |
多项式快速幂
先取对数,然后乘,然后取exp
1 | void poly_pow(int *a,int n,int k,int *b){//a[exn(n+n-1)] // a^k not quick pow but quicker |
多项式三角函数
1 | void poly_sin(int*a,int n,int*b){//a[exn(n+n-1)]// 保证a[0]=0 -> c[0]=0 -> 可以exp |
拉格朗日插值法
。。。。。。没啥可说的,存粹的套路
多项式多点求值
全家桶
1 |
|
- 本文作者: fightinggg
- 本文链接: http://fightinggg.github.io/yilia/yilia/PT8XEX.html
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!