多项式总结及模板

2019-04-14 21:02发布

1.求逆 设要对多项式A求逆,逆为B: 求在模ceil(n/2)的逆,将原式与之相减后平方,发现可得在模n意义下也是0了,然后两边同乘A,移项即可倍增了(注意此时A也是在模当前长度意义下的)。 最后倍增形式为B'=2*B-B*B*A  (b’等于2b减b方a),边界为常数取逆元,也可发现多项式有无逆取决于常数有无逆元 2.开根 与求逆类似,先求ceil(n/2),然后将A移到左边使等式右边变成0,平方,加上4b^2a,再把右边b^2除到左边就发现ok了。 最终倍增形式:B'=(A+B*B)/2B(B'等于A加B方后除以2B),除法就上求逆,边界是常数开根,暴力枚举(并不会二次剩余...)?模板题保证是1... (开根里面套求逆,虽说复杂度仍然是nlog,但已经比大部分两个log慢了。。。)  3.Ln 两边求导得到所求的导数B’=A'/A,再积分即可。 4.Exp B=e^(A) 根据牛顿迭代的那套理论,设一个函数C,使C(B)=0,那么C(B)=LnB-A 假设已知在mod x^n的B0,要求在mod x^2n的B1 有C(B)=C(B0)/0!+C'(B0)/1!*(B-B0)+... 发现...可以省略,因为在mod x^n下B是唯一确定的,而mod x^2n下一定也满足mod x^n下,所以在mod x^2n时后面低的n位与mod x^n相等,当求的导数大于等于二阶发现(B-B0)那一项的幂次大于等于2,也就是最小的x项幂次大于等于2n,省略即可。 最终推得 B1=B0-C(B0)/C'(B0) 而C求导时是在把B0这个多项式看成变量求导(不要把每一项的x看成变量),A是已知多项式要看成一个常数 故B1=B0(1-Ln(B0)+A) 倍增即可。(注意能Exp一定要满足0次项为0,不然无法赋初值)   先贴4个的代码: #include #define ll long long using namespace std; const int mod=998244353; const int N=1e5+100; void Ad(int &x,int y) {if((x+=y)>=mod)x-=mod;} void Mul(int &x,int y) {x=1LL*x*y%mod;} int qpow(int x,int y) { int res=1; while(y) { if(y&1)res=1LL*res*x%mod; x=1LL*x*x%mod,y>>=1; } return res; } namespace Poly{ vectorA,B,C; int wh[N*3],cc,len,n,inv[N*3]; void Pre_Ntt(int l) { cc=0,len=1; while(len<=l)++cc,len<<=1; } void Cal_wh() {for(int i=1;i>1]>>1)|((i&1)<<(cc-1));} void Ntt(vector&a,bool inv) { for(int i=0;i>1,tp=qpow(3,(mod-1)/l); for(int i=0;i&b,int n) { if(n==1){b[0]=qpow(A[0],mod-2);return;} int md=(n+1)/2; vectora,c; Pre_Ntt(n+md+md),a.resize(len),c.resize(len); Get_Inv(c,md); Pre_Ntt(n+md+md),Cal_wh(); for(int i=0;i &a,vector &res,int n) { A=a,res.clear(),res.resize(n); Get_Inv(res,n); } void Get_Sqrt(vector&b,int n) { if(n==1){b[0]=1;return;} int md=(n+1)/2; vectora,c; Pre_Ntt(n+n),a.resize(len),c.resize(len); Get_Sqrt(c,md); for(int i=0;i &a,vector &res,int n) { Pre_Ntt(n+n); B=a,res.clear(),res.resize(len); Get_Sqrt(res,n); } void Dao(vector &a,vector &res,int n) { res.clear(),res.resize(n); for(int i=1;i &a,vector &res,int n) { res.clear(),res.resize(n+1),inv[1]=1; for(int i=2;i<=n;i++) inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod; for(int i=n-1;i>=0;i--) res[i+1]=1LL*a[i]*inv[i+1]%mod; res[0]=0; } void Ln(vector&a,vector &res,int n) { static vectormo,ha; Dao(a,mo,n),Inv(a,ha,n); Pre_Ntt(n+n),Cal_wh(); mo.resize(len),Ntt(mo,0); ha.resize(len),Ntt(ha,0); for(int i=0;i&b1,int n) { if(n==1){b1[0]=1;return;} int md=(n+1)/2; vectorb0; b0.resize(n),b1.resize(n); Get_Exp(b0,md),Ln(b0,b1,n); for(int i=0;i&a,vector &res,int n) {C=a,res.resize(n),Get_Exp(res,n);} } int main() { int n; scanf("%d",&n); vectora,b; a.resize(n); for(int i=0;i