求救,本蒟蒻改的心力憔悴了

P5205 【模板】多项式开根

蒟蒻先%为敬
by info___tion @ 2019-03-15 20:02:38


先%为敬,您还是自己调吧。。。 多项式这种东西看着脑袋都疼
by partychicken @ 2019-03-15 20:16:22


@[partychicken](/space/show?uid=53241) dalao别这样啊
by huhao @ 2019-03-15 20:53:51


@[huhao](/space/show?uid=19410) 你看我这道题都没过的。。。
by partychicken @ 2019-03-15 21:04:33


``` #include<bits/stdc++.h> namespace Poly { const int mod=998244353; const int g=3; int l,N,*r,*A,*B,*C,Size; void Make(int &x) { if(x>=mod) { x-=mod; } } int Kasumi(int a,int b) { int res=1,base=a; while (b) { if(b&1) { res=1ll*res*base%mod; } base=1ll*base*base%mod; b >>= 1; } return res; } void NTT(int *a,int op) { for(register int i=0;i<N;i++) { if(i<r[i]) { std::swap(a[i],a[r[i]]); } } for(register int i=1;i<N;i<<=1) { int one=Kasumi(g,(mod-1) / (i<<1)); if(op==-1) { one=Kasumi(one,mod-2); } for(register int j=0;j<N;j+=i<<1) { for(register int len=0,w=1;len<i;len++,w=1ll*w*one%mod) { int x=a[j+len],y=1ll*w*a[i+j+len]%mod; Make(a[j+len]=x+y); Make(a[i+j+len]=x+mod-y); } } } if(op==-1) { for(register int i=0,inv=Kasumi(N,mod-2);i<N;i++) { a[i]=1ll*a[i]*inv%mod; } } } class Polynomial { private : int *a; Polynomial InvMul(const Polynomial &x) { Polynomial res; res.max=N; res.a=new int[res.max+1]; r=new int[N+1]; r[0]=0; for(register int i=0;i<N;i++) { r[i]=r[i>>1]>>1|(i&1)<<(l-1); } A=new int[N+1],B=new int[N+1]; memset(A,0,(N+1)<<2); memset(B,0,(N+1)<<2); memcpy(A,a,(std::min(max,N-1)+1)<<2); memcpy(B,x.a,(std::min(x.max,N-1)+1)<<2); NTT(A,1),NTT(B,1); for(register int i=0;i<N;i++) { A[i]=1ll*B[i]*(2+mod-1ll*A[i]*B[i]%mod)%mod; } NTT(A,-1); memcpy(res.a,A,(res.max+1)<<2); delete[] A,delete[] B,delete[] r; return res; } Polynomial Reverse() { Polynomial res; res=*this; std::reverse(res.a,res.a+1+max); return res; } Polynomial Direv() { Polynomial res; res.max=max-1; res.a=new int[res.max+1]; for(register int i=1;i<=max;i++) { res.a[i-1]=1ll*a[i]*i%mod; } return res; } Polynomial Inrev() { Polynomial res; res.max=max+1; res.a=new int[res.max+1]; res.a[0]=0; for(register int i=1;i<=max;i++) { res.a[i]=1ll*a[i-1]*Kasumi(i,mod-2)%mod; } return res; } public : int max; Polynomial(int x=0):max(0) { a=new int[1]; a[0]=x; } int& operator [](int x) { return (this->a[x]); } void Init(int m) { delete[] a; a=new int[(max=m)+1]; memset(a,0,(max+1)<<2); } void Init(int *x,int m) { delete[] a; a=new int[(max=m)+1]; memcpy(a,x,(max+1)<<2); } int operator [](int pos) const { if(pos>max) { return 0; } return this->a[pos]; } Polynomial operator*(const Polynomial &x) const { Polynomial res; res.max=max+x.max; res.a=new int[res.max+1]; for(l=0,N=1;N<=res.max;N<<=1) { l++; } r=new int[N+1]; r[0]=0; for(register int i=0;i<N;i++) { r[i]=r[i>>1]>>1|(i&1)<<(l-1); } A=new int[N+1],B=new int[N+1]; memset(A,0,(N+1)<<2),memset(B,0,(N+1)<<2); memcpy(A,a,(max+1)<<2),memcpy(B,x.a,(x.max+1)<<2); NTT(A,1),NTT(B,1); for(register int i=0;i<N;i++) { A[i]=1ll*A[i]*B[i]%mod; } NTT(A,-1); memcpy(res.a,A,(res.max+1)<<2); delete[] A,delete[] B,delete[] r; return res; } Polynomial operator*(int x) const { Polynomial res; res.max=max; res.a=new int[res.max+1]; for(register int i=0;i<=res.max;i++) { res.a[i]=1ll*x*a[i]%mod; } return res; } Polynomial operator+(const Polynomial &x) const { Polynomial res; res.max=std::max(max,x.max); res.a=new int[res.max+1]; for(register int i=0;i<=res.max;i++) { res.a[i]=0; if(i<=max) { res.a[i]=a[i]; } if(i<=x.max) { Make(res.a[i]+=x.a[i]); } } return res; } Polynomial operator-(const Polynomial &x) const { Polynomial res; res.max=std::max(max,x.max); res.a=new int[res.max+1]; for(register int i=0;i<=res.max;i++) { res.a[i]=0; if(i<=max) { res.a[i]=a[i]; } if(i<=x.max) { Make(res.a[i]+=mod-x.a[i]); } } return res; } typedef std::pair<Polynomial,Polynomial> DivAns; DivAns operator / (Polynomial &x) { Polynomial res,rem,tmp; int p=max-x.max+1; res=(Reverse()%p*((x.Reverse())%p).Inv()%p).Reverse(); tmp=x*res; rem.max=x.max-1; rem.a=new int[rem.max+1]; for(register int i=0;i<=rem.max;i++) { rem.a[i]=a[i]; if(i<=tmp.max) { Make(rem.a[i]+=mod-tmp.a[i]); } } return std::make_pair(res,rem); } Polynomial operator%(int x) const { Polynomial res; res.max=x-1; res.a=new int[res.max+1]; memset(res.a,0,(res.max+1)<<2); memcpy(res.a,a,(std::min(max,res.max)+1)<<2); return res; } Polynomial& operator=(const Polynomial &x) { if(this->a != x.a) { delete[] a; } a=new int[(max=x.max)+1]; memcpy(a,x.a,(max+1)<<2); return *this; } Polynomial Inv() { Polynomial p[2]; int now=0,last=1,len=1; p[now].max=0,p[now].a=new int(Kasumi(a[0],mod-2)); for(len=1,N=2,l=1;len<=(max<<1);N<<=1,l++,len<<=1) { std::swap(now,last); p[now]=p[last]*2; p[last]=p[last]*p[last]%(len<<1)*(*this%(len<<1))%(len<<1); p[now]=p[now]-p[last]; } return p[now]%(max+1); } Polynomial Ln() { return (Direv()*Inv()%(max+1)).Inrev()%(max+1); } Polynomial Exp() { Polynomial p[2]; int now=0,last=1; p[now]=Polynomial(1); for(register int len=1;len<=(max<<1);len<<=1) { std::swap(now,last); p[now]=p[last]; p[last]=p[last]*(p[last].Ln()-(*this%(len<<1)))%(len<<1); p[now]=p[now]-p[last]; } return p[now]%(max+1); } void Print() { for(register int i=0;i<=max;i++) { printf("%d ",a[i]); } putchar('\n'); } Polynomial Sqrt() { Polynomial p[2]; int now=0,last=1,len=1; p[now]=Polynomial(this->a[0]); for(len=1,N=2,l=1;len<=(max<<1);N<<=1,l++,len<<=1) { std::swap(now,last); p[now]=(p[last]*2).Inv(); p[last]=p[last]*p[last]%(len<<1); p[now]=(*this%(len<<1)+p[last])*p[now]%(len<<1); } return p[now]%(max+1); } }; typedef std::pair<Polynomial,Polynomial> DivAns; } using namespace std; using namespace Poly; ``` 您看一下吧
by partychicken @ 2019-03-15 21:06:20


@[partychicken](/space/show?uid=53241) fake! 我变量用重了…… 回文树的wiki估计要重构了
by huhao @ 2019-03-17 19:36:04


@[huhao](/space/show?uid=19410) 您看我改的那些怎么样,如果您没有意见我就直接改了
by partychicken @ 2019-03-18 07:31:40


@[partychicken](/space/show?uid=53241) 您改的都很好啊
by huhao @ 2019-03-18 08:07:05


@[huhao](/space/show?uid=19410) 那我改了,改您的东西总要征求一下您的意见的
by partychicken @ 2019-03-18 09:00:31


|