1. 程式人生 > >多項式模板 - 2018-12-30

多項式模板 - 2018-12-30

 

 

 

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL read(){
    LL x=0,f=0;
    char ch=getchar();
    while (!isdigit(ch))
        f|=ch=='-',ch=getchar();
    while (isdigit(ch))
        x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    
return f?-x:x; } const int N=1<<18,mod=998244353; void Add(int &x,int y){ if ((x+=y)>=mod) x-=mod; } void Del(int &x,int y){ if ((x-=y)<0) x+=mod; } int del(int x,int y){ return x-y<0?x-y+mod:x-y; } int Pow(int x,int y){ int ans=1;
for (;y;y>>=1,x=(LL)x*x%mod) if (y&1) ans=(LL)ans*x%mod; return ans; } int randint(){ return ((rand()&65535)<<15)^(rand()&65535); } namespace Rem2{ int INIT_TAG=0; int t,w; #define fi first #define se second void init(){ INIT_TAG
=1; srand('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I'); } pair <int,int> Mul_pii(pair <int,int> A,pair <int,int> B){ static int a,b; a=((LL)A.fi*B.fi+(LL)A.se*B.se%mod*w)%mod; b=((LL)A.fi*B.se+(LL)A.se*B.fi)%mod; return make_pair(a,b); } pair <int,int> Pow_pii(pair <int,int> x,int y){ pair <int,int> ans=make_pair(1,0); for (;y;y>>=1,x=Mul_pii(x,x)) if (y&1) ans=Mul_pii(ans,x); return ans; } int Sqrt(int x){ if (!INIT_TAG) init(); if (x==0) return 0; if (Pow(x,(mod-1)/2)!=1) return -1; do { t=randint()%(mod-1)+1; w=((LL)t*t+mod-x)%mod; } while (Pow(w,(mod-1)/2)==1); pair <int,int> res=Pow_pii(make_pair(t,1),(mod+1)/2); return min(res.fi,mod-res.fi); } } namespace Polynomial{ namespace Fast{ const int N=1<<18; int n,Log[N+1],Fac[N+1],InvFac[N+1],Inv[N+1]; int ww[N*2],*Ew=ww,*w[N+1]; int iww[N*2],*Ei=iww,*iw[N+1]; int INIT_TAG=0; void init(int _n){ INIT_TAG=1; Log[1]=0,n=_n; for (int i=2;i<=N;i++) Log[i]=Log[i>>1]+1; for (int i=Fac[0]=1;i<=N;i++) Fac[i]=(LL)Fac[i-1]*i%mod; InvFac[N]=Pow(Fac[N],mod-2); for (int i=N;i>=1;i--) InvFac[i-1]=(LL)InvFac[i]*i%mod; for (int i=1;i<=N;i++) Inv[i]=(LL)InvFac[i]*Fac[i-1]%mod; for (int d=0;d<=Log[n];d++){ w[d]=Ew,iw[d]=Ei; int n=1<<d; w[d][0]=1,w[d][1]=Pow(3,(mod-1)/n); for (int i=2;i<n;i++) w[d][i]=(LL)w[d][i-1]*w[d][1]%mod; iw[d][0]=1,iw[d][1]=Pow(w[d][1],mod-2); for (int i=2;i<n;i++) iw[d][i]=(LL)iw[d][i-1]*iw[d][1]%mod; Ew+=n,Ei+=n; } } int Rev[N+1],A[N+1],B[N+1]; void FFT(int a[],int n,int **w){ if (!INIT_TAG) init(N); for (int i=0;i<n;i++) if (Rev[i]<i) swap(a[i],a[Rev[i]]); for (int t=1,d=1;d<n;t++,d<<=1) for (int i=0;i<n;i+=(d<<1)) for (int j=0,*W=w[t];j<d;j++){ int tmp=(LL)(*W++)*a[i+j+d]%mod; a[i+j+d]=del(a[i+j],tmp); Add(a[i+j],tmp); } } vector <int> Mul(vector <int> &a,vector <int> &b){ static vector <int> res; res.clear(); LL Br=(LL)a.size()*b.size(); LL FF=(a.size()+b.size())*Log[a.size()+b.size()]*10+100; if (Br<=FF){ for (int i=0;i<a.size()+b.size();i++) res.push_back(0); for (int i=0;i<a.size();i++) for (int j=0;j<b.size();j++) res[i+j]=((LL)a[i]*b[j]+res[i+j])%mod; } else { int n=1,d=0; for (;n<a.size()+b.size();n<<=1,d++); for (int i=0;i<n;i++) Rev[i]=(Rev[i>>1]>>1)|((i&1)<<(d-1)),A[i]=B[i]=0; for (int i=0;i<a.size();i++) A[i]=a[i]; for (int i=0;i<b.size();i++) B[i]=b[i]; // w[0]=1,w[1]=Pow(3,(mod-1)/n); // for (int i=2;i<n;i++) // w[i]=(LL)w[i-1]*w[1]%mod; FFT(A,n,w),FFT(B,n,w); for (int i=0;i<n;i++) A[i]=(LL)A[i]*B[i]%mod; // w[1]=Pow(w[1],mod-2); // for (int i=2;i<n;i++) // w[i]=(LL)w[i-1]*w[1]%mod; FFT(A,n,iw); int inv=Pow(n,mod-2); for (int i=0;i<n;i++) res.push_back((int)((LL)inv*A[i]%mod)); } while (!res.empty()&&!res.back()) res.pop_back(); return res; } vector <int> MulInv(vector <int> &a,vector <int> &b){ static vector <int> res; res.clear(); int n=1,d=0; for (;n<a.size()*2+b.size();n<<=1,d++); for (int i=0;i<n;i++) Rev[i]=(Rev[i>>1]>>1)|((i&1)<<(d-1)),A[i]=B[i]=0; for (int i=0;i<a.size();i++) A[i]=a[i]; for (int i=0;i<b.size();i++) B[i]=b[i]; // w[0]=1,w[1]=Pow(3,(mod-1)/n); // for (int i=2;i<n;i++) // w[i]=(LL)w[i-1]*w[1]%mod; FFT(A,n,w),FFT(B,n,w); for (int i=0;i<n;i++) A[i]=(LL)A[i]*A[i]%mod*B[i]%mod; // w[1]=Pow(w[1],mod-2); // for (int i=2;i<n;i++) // w[i]=(LL)w[i-1]*w[1]%mod; FFT(A,n,iw); int inv=Pow(n,mod-2); for (int i=0;i<n;i++) res.push_back((int)((LL)inv*A[i]%mod)); while (!res.empty()&&!res.back()) res.pop_back(); return res; } } struct Poly{ vector <int> v; Poly(){ v.clear(); } Poly(int x){ v.clear(); v.push_back(x); } Poly(vector <int> x){ v=x; } int operator ()(int x){ int ans=0,y=1; for (int i=0;i<v.size();i++) ans=((LL)v[i]*y+ans)%mod,y=(LL)y*x%mod; return ans; } int size(){ return v.size(); } void print(){ for (int i=0;i<v.size();i++) printf("%d ",v[i]); } void print(int x){ for (int i=0;i<x;i++) printf("%d ",i>=v.size()?0:v[i]); } void print(string s){ print(),cout << s; } void clear(){ v.clear(); } void push_back(int x){ v.push_back(x); } void pop_back(){ v.pop_back(); } int empty(){ return v.empty(); } int back(){ return v.back(); } int &operator [](int x){ return v[x]; } void operator += (Poly A){ while (v.size()<A.size()) v.push_back(0); for (int i=0;i<A.size();i++) Add(v[i],A[i]); } void operator -= (Poly &A){ while (v.size()<A.size()) v.push_back(0); for (int i=0;i<A.size();i++) Del(v[i],A[i]); } void operator *= (Poly &A); void Derivation(){ for (int i=0;i<v.size()-1;i++) v[i]=(LL)v[i+1]*(i+1)%mod; v.pop_back(); } void Integral(){ v.push_back(0); for (int i=v.size()-2;i>=0;i--) v[i+1]=(LL)v[i]*Fast :: Inv[i+1]%mod; v[0]=0; } void operator *= (int x){ for (int i=0;i<v.size();i++) v[i]=(LL)v[i]*x%mod; } }pp; //struct Poly end------------- Poly operator + (Poly A,Poly B){ pp.clear(); for (int i=0;i<max(A.size(),B.size());i++) pp.push_back(0); for (int i=0;i<A.size();i++) Add(pp[i],A[i]); for (int i=0;i<B.size();i++) Add(pp[i],B[i]); return pp; } Poly operator - (Poly A,Poly B){ pp.clear(); for (int i=0;i<max(A.size(),B.size());i++) pp.push_back(0); for (int i=0;i<A.size();i++) Add(pp[i],A[i]); for (int i=0;i<B.size();i++) Del(pp[i],B[i]); return pp; } Poly operator * (Poly A,Poly B){ return Poly(Fast :: Mul(A.v,B.v)); } void Poly :: operator *= (Poly &A){ v=Fast :: Mul(v,A.v); } Poly operator * (Poly A,int x){ pp=A; for (int i=0;i<A.size();i++) pp[i]=(LL)pp[i]*x%mod; return pp; } Poly Inverse(Poly a,int n); Poly operator / (Poly A,Poly B){//Divide int n=A.size(),m=B.size(); reverse(A.v.begin(),A.v.end()); reverse(B.v.begin(),B.v.end()); int k=n-m+1; if (k<0) return Poly(0); while (A.size()>k) A.pop_back(); while (B.size()>k) B.pop_back(); A=A*Inverse(B,k); while (A.size()>k) A.pop_back(); reverse(A.v.begin(),A.v.end()); return A; } Poly operator % (Poly A,Poly B){//Modulo while (!A.empty()&&!A.back()) A.pop_back(); while (!B.empty()&&!B.back()) B.pop_back(); A=A-A/B*B; while (A.size()>=B.size()) A.pop_back(); while (!A.empty()&&!A.back()) A.pop_back(); return A; } Poly Derivation(Poly A){ for (int i=0;i<A.size()-1;i++) A[i]=(LL)A[i+1]*(i+1)%mod; A.pop_back(); return A; } Poly Integral(Poly A){ A.push_back(0); for (int i=A.size()-2;i>=0;i--) A[i+1]=(LL)A[i]*Fast :: Inv[i+1]%mod; A[0]=0; return A; } Poly Inverse(Poly a,int n){ static Poly A,B; while (!a.empty()&&!a.back()) a.pop_back(); if (a.empty()) return a; A.clear(),B.clear(); B.push_back(a[0]); A.push_back(Pow(B[0],mod-2)); for (int t=1;t<n;){ for (int i=t;i<min(a.size(),(t<<1));i++) B.push_back(a[i]); t<<=1; A=A*2-Poly(Fast :: MulInv(A.v,B.v)); while (A.size()>t) A.pop_back(); } while (A.size()>n) A.pop_back(); return A; } Poly Sqrt(Poly a,int n){ static Poly A,B; while (!a.empty()&&!a.back()) a.pop_back(); if (a.empty()) return a; A.clear(),B.clear(); B.push_back(a[0]); A.push_back(Rem2 :: Sqrt(B[0])); for (int t=1;t<n;){ for (int i=t;i<min(a.size(),(t<<1));i++) B.push_back(a[i]); t<<=1; A+=B*Inverse(A,t); while (A.size()>t) A.pop_back(); A*=499122177; } if (A[0]>mod-A[0]) for (int i=0;i<A.size();i++) A[i]=(mod-A[i])%mod; while (A.size()>n) A.pop_back(); return A; } Poly Ln(Poly a,int n){ while (!a.empty()&&!a.back()) a.pop_back(); if (a.empty()||a[0]!=1) return a; a=Integral(Derivation(a)*Inverse(a,n)); while (a.size()>n) a.pop_back(); return a; } Poly Exp(Poly a,int n){ static Poly A,B; while (!a.empty()&&!a.back()) a.pop_back(); if (a.empty()) return Poly(1); if (a[0]!=0) return a; A.clear(),B.clear(); B.push_back(1); A.push_back(a[0]); for (int t=1;t<n;){ for (int i=t;i<min(a.size(),(t<<1));i++) A.push_back(a[i]); t<<=1; B=B*(Poly(1)+A-Ln(B,t)); while (B.size()>t) B.pop_back(); } while (B.size()>n) B.pop_back(); return B; } Poly PolyPow(Poly x,int y,int n){ static Poly A,B; int k0=0,kc,ivkc; while (!x.empty()&&!x.back()) x.pop_back(); if (x.empty()) return x; while (k0<x.size()&&x[k0]==0) k0++; kc=x[k0],ivkc=Pow(kc,mod-2); A.clear(); for (int i=k0;i<x.size();i++) A.push_back((int)((LL)x[i]*ivkc%mod)); A=Exp(Ln(A,n)*y,n); B.clear(); if ((LL)k0*y>=n) return B; kc=Pow(kc,y),k0*=y; for (int i=0;i<k0;i++) B.push_back(0); for (int i=0;i<min(A.size(),n-k0);i++) B.push_back((int)((LL)A[i]*kc%mod)); while (B.size()>n) B.pop_back(); return B; } namespace Qiuzhi{ Poly P[N<<2],f[N<<2],M; vector <int> x,y; int n; void GetP(int rt,int L,int R){ if (L==R){ P[rt].clear(); P[rt].push_back((mod-x[L])%mod); P[rt].push_back(1); return; } int mid=(L+R)>>1,ls=rt<<1,rs=ls|1; GetP(ls,L,mid); GetP(rs,mid+1,R); P[rt]=P[ls]*P[rs]; } void qiuzhi(int rt,int L,int R){ if (f[rt].empty()) f[rt].push_back(0); if (L==R) return (void)(y[L]=f[rt][0]); int mid=(L+R)>>1,ls=rt<<1,rs=ls|1; f[ls]=f[rt]%P[ls]; f[rs]=f[rt]%P[rs]; qiuzhi(ls,L,mid); qiuzhi(rs,mid+1,R); } vector <int> Get_Val(vector <int> A,Poly F){ n=A.size(); x.clear(),y.clear(); for (int i=0;i<n;i++){ x.push_back(A[i]); y.push_back(0); } GetP(1,0,n-1); f[1]=F; qiuzhi(1,0,n-1); return y; } } namespace Chazhi{ Poly P[N<<2],M; vector <int> x,y; int n; void GetP(int rt,int L,int R){ if (L==R){ P[rt].clear(); P[rt].push_back((mod-x[L])%mod); P[rt].push_back(1); return; } int mid=(L+R)>>1,ls=rt<<1,rs=ls|1; GetP(ls,L,mid); GetP(rs,mid+1,R); P[rt]=P[ls]*P[rs]; } Poly chazhi(int rt,int L,int R){ if (L==R) return Poly(y[L]); int mid=(L+R)>>1,ls=rt<<1,rs=ls|1; return chazhi(ls,L,mid)*P[rs]+chazhi(rs,mid+1,R)*P[ls]; } Poly Get_Poly(vector <int> A,vector <int> B){ n=A.size(); x=A; int Product=1; GetP(1,0,n-1); M=Derivation(P[1]); y=Qiuzhi :: Get_Val(A,M); for (int i=0;i<y.size();i++) y[i]=(LL)B[i]*Pow(y[i],mod-2)%mod; return chazhi(1,0,n-1); } } }// be careful about init!!!!!! using namespace Polynomial; Poly A,B; vector <int> x,y; int main(){ int n=read()+1,k=read(); A.clear(); for (int i=0;i<n;i++) A.push_back(read()); B=Exp(Integral(Inverse(Sqrt(A,n),n)),n); B=Poly(1)+Ln(Poly(2)+A-A(0)-B,n); B=Derivation(PolyPow(B,k,n)); n--; B.print(n); return 0; }
Polynomial