多项式全家桶
#include<bits/stdc++.h>
#define LL long long
using namespace std;
namespace Poly
{
const int mod=998244353,_G=3,_Gi=332748118,Mx=2100000;
int _w[Mx+2],_inv[Mx+2],FAC[Mx+2],INV[Mx+2];
typedef pair<int,int> P;
mt19937 _rnd(0);
inline void Print(vector<int> A)
{
for(int i=0;i<A.size();++i)printf("%d ",A[i]);
puts("");
}
inline LL Pow(LL a,int b)
{
LL c=1;
for(;b;b>>=1,(a*=a)%=mod)if(b&1)(c*=a)%=mod;
return c;
}
inline void add(int &x,int y)
{
if((x+=y)>=mod)x-=mod;
}
inline vector<int> Add(vector<int> A,vector<int> B)
{
int n=max(A.size(),B.size());
A.resize(n),n=B.size();
for(int i=0;i<n;++i)add(A[i],B[i]);
return A;
}
inline vector<int> Mul(vector<int> A,int k)
{
if(k<0)k+=mod;
for(int i=0;i<A.size();++i)A[i]=((LL)A[i]*k)%mod;
return A;
}
inline void Init()
{
int len,mid,W;
len=(1<<(int)log2(Mx)),mid=len>>1,W=Pow(_G,(mod-1)/len),_w[mid]=_inv[1]=1;
for(int i=2;i<=Mx;++i)_inv[i]=((LL)(mod-mod/i)*_inv[mod%i])%mod;
for(int i=mid+1;i<len;++i)_w[i]=((LL)_w[i-1]*W)%mod;
for(int i=mid-1;i>=0;--i)_w[i]=_w[i<<1];
FAC[0]=INV[0]=1;for(int i=1;i<=Mx;++i)FAC[i]=((LL)FAC[i-1]*i)%mod,INV[i]=((LL)INV[i-1]*_inv[i])%mod;
}
inline LL Binom(int a,int b)
{
return (LL)FAC[a]*INV[b]%mod*INV[a-b]%mod;
}
inline void DFT(vector<int> &A)
{
int n=A.size(),tmp;
for(int i=(n>>1);i;i>>=1)for(int j=0;j<n;j+=(i<<1))for(int k=0;k<i;++k)tmp=A[i+j+k],A[i+j+k]=((LL)(A[j+k]-tmp+mod)*_w[i+k])%mod,add(A[j+k],tmp);
}
inline void IDFT(vector<int> &A)
{
int n=A.size(),tmp;
for(int i=1;i<n;i<<=1)for(int j=0;j<n;j+=(i<<1))for(int k=0;k<i;++k)tmp=((LL)A[i+j+k]*_w[i+k])%mod,add(A[i+j+k]=A[j+k],mod-tmp),add(A[j+k],tmp);
for(int i=1;i<n-i;++i)swap(A[i],A[n-i]);
}
inline vector<int> Mul(vector<int> A,vector<int> B)
{
int n=A.size()-1,m=B.size()-1,len,inv;
for(len=1;len<=n+m;len<<=1);
inv=_inv[len],A.resize(len),B.resize(len),DFT(A),DFT(B);
for(int i=0;i<len;++i)A[i]=((LL)A[i]*B[i])%mod;
IDFT(A),A.resize(n+m+1);
for(int i=0;i<A.size();++i)A[i]=((LL)A[i]*inv)%mod;
return A;
}
inline vector<int> Mul2(vector<int> A)
{
int n=A.size()-1,len,inv;
for(len=1;len<=n+n;len<<=1);
inv=_inv[len],A.resize(len),DFT(A);
for(int i=0;i<len;++i)A[i]=((LL)A[i]*A[i])%mod;
IDFT(A),A.resize(n+n+1);
for(int i=0;i<A.size();++i)A[i]=((LL)A[i]*inv)%mod;
return A;
}
inline vector<int> Inv(vector<int> &A,int k)
{
vector<int> B,C;
B.push_back(Pow(A[0],mod-2));
for(int l=2,x;l<=(k<<1);l<<=1)
{
C.resize(x=min(l,(int)A.size()));
for(int i=0;i<x;++i)C[i]=A[i];
C=Mul(Mul(C,B),-1),add(C[0],2),(B=Mul(B,C)).resize(l);
}
return B.resize(k),B;
}
inline int Cipolla(int k)
{
if(!k)return 0;
int a,b=((mod+1)>>1),I;
for(;Pow((a=abs((int)_rnd()),I=((((LL)a*a-k)%mod)+mod)%mod),(mod-1)>>1)==1;);
P p=P(1,0),t=P(a,1);
for(;b;b>>=1)
{
if(b&1)p=P(((LL)p.first*t.first+(((LL)p.second*t.second)%mod)*I)%mod,((LL)p.first*t.second+(LL)t.first*p.second)%mod);
t=P(((LL)t.first*t.first+(((LL)t.second*t.second)%mod)*I)%mod,((LL)t.first*t.second*2)%mod);
}
return min(p.first,mod-p.first);
}
inline vector<int> Sqrt(vector<int> &A,int k)
{
vector<int> B,C;
B.push_back(Cipolla(A[0]));
for(int l=2,x;l<=(k<<1);l<<=1)
{
C.resize(x=min(l,(int)A.size()));
for(int i=0;i<x;++i)C[i]=A[i];
(B=Mul(Mul(Add(Mul(B,B),C),Inv(B,l)),(mod+1)/2)).resize(l);
}
return B.resize(k),B;
}
inline vector<int> Der(vector<int> A)
{
for(int i=1;i<A.size();++i)A[i-1]=((LL)A[i]*i)%mod;
return A.pop_back(),A;
}
inline vector<int> Int(vector<int> A)
{
A.push_back(0);
for(int i=A.size()-1;i;--i)A[i]=((LL)A[i-1]*_inv[i])%mod;
return A[0]=0,A;
}
inline vector<int> Ln(vector<int> A,int k)
{
return (A=Int(Mul(Der(A),Inv(A,k)))).resize(k),A;
}
inline vector<int> Exp(vector<int> &A,int k)
{
vector<int> B,C;
B.push_back(1);
for(int l=2,x;l<=(k<<1);l<<=1)
{
C.resize(x=min(l,(int)A.size()));
for(int i=0;i<x;++i)C[i]=A[i];
C=Add(C,Mul(Ln(B,l),-1)),add(C[0],1),(B=Mul(B,C)).resize(l);
}
return B.resize(k),B;
}
inline vector<int> Pow(vector<int> A,char *s,int k)
{
int t,b=0,b2=0,a,inv,l=strlen(s+1);
LL tmp;
for(int i=1;i<=l;++i)tmp=(LL)b*10+(s[i]^48),b=(tmp<mod? tmp:(tmp%mod)+mod),tmp=(LL)b2*10+(s[i]^48),b2=(tmp<mod-1? tmp:(tmp%(mod-1))+mod-1);
for(t=0;t<A.size() && !A[t];++t);
if(t==A.size() || (t && b2>A.size()/t) || k<=t)return A.resize(0),A.resize(k),A;
inv=Pow(a=A[t],mod-2);
for(int i=t;i<A.size();++i)A[i-t]=((LL)A[i]*inv)%mod;
A.resize(k-t),(A=Mul(Exp(A=Mul(Ln(A,k),b),k),Pow(a,b2))).resize(A.size()+(t*=b2));
for(int i=A.size()-1;i>=t;--i)A[i]=A[i-t];
for(int i=0;i<t;++i)A[i]=0;
return A.resize(k),A;
}
inline vector<int> Pow(vector<int> A,LL s,int k)
{
int t,b=(s<mod? s:(s%mod)+mod),b2=(s<mod-1? s:(s%(mod-1))+mod-1),a,inv;
for(t=0;t<A.size() && !A[t];++t);
if(t==A.size() || (t && b2>A.size()/t) || k<=t)return A.resize(0),A.resize(k),A;
inv=Pow(a=A[t],mod-2);
for(int i=t;i<A.size();++i)A[i-t]=((LL)A[i]*inv)%mod;
A.resize(k-t),A=Mul(Exp(A=Mul(Ln(A,k),b),k),Pow(a,b2)),t*=b2,A.resize(k);
for(int i=k-1;i>=t;--i)A[i]=A[i-t];
for(int i=min(t,k)-1;~i;--i)A[i]=0;
return A;
}
inline void Rev(vector<int> &A)
{
for(int i=0;(i<<1)+1<A.size();++i)swap(A[i],A[A.size()-i-1]);
}
inline vector<int> Div(vector<int> A,vector<int> B)
{
int n=A.size(),m=B.size();
if(n<m)return vector<int>{0};
return Rev(A),Rev(B),(A=Mul(A,Inv(B,n-m+1))).resize(n-m+1),Rev(A),A;
}
inline vector<int> Mod(vector<int> A,vector<int> &B)
{
if(A.size()<B.size())return A;
return (A=Add(A,Mul(Mul(B,Div(A,B)),-1))).resize(B.size()-1),A;
}
inline vector<int> Shift(vector<int> A,int c)
{
int n=A.size();
vector<int> B;
B.resize(n),c=(c%mod+mod)%mod;
for(int i=0;i<n;++i)A[i]=((LL)A[i]*FAC[i])%mod,B[i]=(i? (LL)B[i-1]*c%mod*_inv[i]%mod:1)%mod;
Rev(A),A=Mul(A,B),A.resize(n),Rev(A);
for(int i=0;i<n;++i)A[i]=((LL)A[i]*INV[i])%mod;
return A;
}
inline void Maintain(vector<int> &A)
{
int n=A.size(),t=0;
for(int i=0;i<n;++i)add(A[i],mod+t),t=A[i]/10,A[i]%=10;
for(;t;t/=10)A.push_back(t%10);
}
inline bool Cmp(vector<int> &A,vector<int> &B)
{
int n=A.size();
if(n<B.size())return 1;
if(n>B.size())return 0;
for(int i=n-1;~i;--i)
{
if(A[i]<B[i])return 1;
if(A[i]>B[i])return 0;
}
return 0;
}
inline void Solve()
{
Init();
}
};
int main()
{
Poly::Solve();
return 0;
}
把相关代码放在 solve
函数里即可运行。