$\text{O}(n \log n)$ 多项式运算
原本的板子有点拉胯,贴个少一些操作的快速板子(然而有些清空和封装没做好)
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
#define maxn 3003003
const int G=3,mod=998244353;
template<class T>
inline T read(){
T r=0,f=0;
char c;
while(!isdigit(c=getchar()))f|=(c=='-');
while(isdigit(c))r=(r<<1)+(r<<3)+(c^48),c=getchar();
return f?-r:r;
}
inline long long qpow(long long a,int b){
long long ans=1;
for(;b;b>>=1){
if(b&1)(ans*=a)%=mod;
(a*=a)%=mod;
}
return ans;
}
namespace Poly{//Need Init
int Lst,g[maxn],rev[maxn];
long long frac[maxn],invf[maxn],inv[maxn];
inline void Add(int &x,int y){
x+=y-mod,x+=(x>>31)&mod;
}
inline void Sub(int &x,int y){
x-=y,x+=(x>>31)&mod;
}
inline void clr(int *f,int n){
for(int i=0;i<n;i++)f[i]=0;
}
inline void cpy(int *f,int *g,int n){
for(int i=0;i<n;i++)f[i]=g[i];
}
inline void T(int n,int *f){
std::reverse(f,f+n);
}
inline void Der(int n,int *f){
for(int i=0;i<n-1;i++)
f[i]=f[i+1]*(i+1ll)%mod;
f[n-1]=0;
}
inline void Int(int n,int *f){
for(int i=n-1;i;i--)
f[i]=f[i-1]*inv[i]%mod;
f[0]=0;
}
inline void init(int n){
frac[0]=1;
for(int i=1;i<n;i++)
frac[i]=frac[i-1]*i%mod;
invf[n-1]=qpow(frac[n-1],mod-2);
for(int i=n-1;i;i--){
invf[i-1]=invf[i]*i%mod;
inv[i]=invf[i]*frac[i-1]%mod;
}
int N=1;
for(;N<n;N<<=1);
for(int i=1;i<N;i<<=1){
g[i]=1;
int p=i<<1;
long long x=qpow(G,(mod-1)/p);
for(int j=i+1;j<p;j++)
g[j]=g[j-1]*x%mod;
}
}
inline void init_rev(int N){
if(N==Lst)return;
for(int i=1;i<N;i++)
rev[i]=(rev[i>>1]>>1)|(i&1?N>>1:0);
Lst=N;
}
inline void NTT(int N,int *f,bool opt){
static unsigned long long A[maxn];
for(int i=0;i<N;i++)A[i]=f[rev[i]];
for(int i=1;i<N;i<<=1)
for(int j=0,p=i<<1;j<N;j+=p)
for(int k=0;k<i;k++){
int l=j|k,r=i|l;
int val=A[r]*g[i|k]%mod;
A[r]=A[l]+mod-val,A[l]+=val;
}
if(!opt){
for(int i=0;i<N;i++)
f[i]=A[i]%mod;
return;
}
int invn=mod-(mod-1)/N;
f[0]=A[0]%mod*invn%mod;
for(int i=1;i<N;i++)
f[i]=A[N-i]%mod*invn%mod;
}
int A[maxn],B[maxn],C[maxn],D[maxn];
inline void Inv(int N,int *f,int *invf){
invf[0]=qpow(f[0],mod-2);
for(int len=2;len<=N;len<<=1){
init_rev(len);
cpy(A,f,len);
cpy(B,invf,len>>1);
NTT(len,A,0),NTT(len,B,0);
for(int i=0;i<len;i++)
A[i]=1ll*A[i]*B[i]%mod,B[i]=0;
NTT(len,A,1),clr(A,len>>1),NTT(len,A,0);
cpy(B,invf,len>>1),NTT(len,B,0);
for(int i=0;i<len;i++)
A[i]=1ll*A[i]*B[i]%mod,B[i]=0;
NTT(len,A,1),clr(A,len>>1);
for(int i=len>>1;i<len;i++)
invf[i]=mod-A[i],A[i]=0;
}
}
inline void Ln(int N,int *f,int *lnf){
Inv(N,f,lnf);
cpy(B,f,N),Der(N,B);
init_rev(N<<=1);
NTT(N,lnf,0),NTT(N,B,0);
for(int i=0;i<N;i++)
lnf[i]=1ll*lnf[i]*B[i]%mod,B[i]=0;
NTT(N,lnf,1),N>>=1,clr(lnf+N,N);
Int(N,lnf);
}
inline void Exp(int N,int *f,int *expf){
expf[0]=1;
for(int len=2;len<=N;len<<=1){
cpy(C,expf,len>>1),Ln(len,C,D);
for(int i=0;i<len;i++)
if((A[i]=f[i]+mod-D[i])>=mod)A[i]-=mod;
init_rev(len),NTT(len,A,0),NTT(len,C,0);
for(int i=0;i<len;i++)
A[i]=1ll*A[i]*C[i]%mod,C[i]=0;
NTT(len,A,1),clr(A,len>>1);
for(int i=len>>1;i<len;i++)
expf[i]=A[i],A[i]=0;
}
}
template<int MAXN>
struct Polyn{
int n,f[MAXN];
int& operator [](const int x){return f[x];}
Polyn& operator +=(int b){
Add(f[0],b);
return (*this);
}
Polyn& operator +=(Polyn &b){
while(n<b.n)f[n++]=0;
for(int i=0;i<b.n;i++)Add(f[i],b[i]);
return (*this);
}
Polyn& operator -=(int b){
Sub(f[0],b);
return (*this);
}
Polyn& operator -=(Polyn &b){
while(n<b.n)f[n++]=0;
for(int i=0;i<b.n;i++)Sub(f[i],b[i]);
return (*this);
}
Polyn& operator *=(long long b){
for(int i=0;i<n;i++)
f[i]=f[i]*b%mod;
return (*this);
}
Polyn& operator *=(Polyn &b){
int N=1;
for(;N<n+b.n-1;N<<=1);
init_rev(N);
for(int i=0;i<b.n;i++)A[i]=b[i];
NTT(N,f,0),NTT(N,A,0);
for(int i=0;i<N;i++)
f[i]=1ll*f[i]*A[i]%mod,A[i]=0;
NTT(N,f,1),n=n+b.n-1,clr(f+n,N-n);
return (*this);
}
Polyn operator +(int b) const{
Polyn c(*this);
return c+=b;
}
Polyn operator +(Polyn &b) const{
Polyn c(*this);
return c+=b;
}
Polyn operator -(int b) const{
Polyn c(*this);
return c-=b;
}
Polyn operator -(Polyn &b) const{
Polyn c(*this);
return c-=b;
}
Polyn operator *(long long b) const{
Polyn c(*this);
return c*=b;
}
Polyn operator *(Polyn &b) const{
Polyn c(*this);
return c*=b;
}
inline Polyn T(){
Polyn b(*this);
std::reverse(b,b+b.n);
return b;
}
inline Polyn Der(){
Polyn b(*this);
for(int i=0;i<n-1;i++)
b[i]=b[i+1]*(i+1ll)%mod;
b[b.n--]=0;
return b;
}
inline Polyn Int(){
Polyn b(*this);
for(int i=b.n;i;i--)
b[i]=b[i-1]*inv[i]%mod;
b[0]=0,b.n++;
return b;
}
inline Polyn Inv(int m=0){
int N=1;
Polyn b(*this);
for(m=!m?n:m;N<m;N<<=1);
Poly::Inv(N,f,b.f),clr(b.f+m,N-m);
return b;
}
inline Polyn Ln(int m=0){
int N=1;
Polyn b(*this);
for(m=!m?n:m;N<m;N<<=1);
Poly::Ln(N,f,b.f),clr(b.f+m,N-m);
return b;
}
inline Polyn Exp(int m=0){
int N=1;
Polyn b(*this);
for(m=!m?n:m;N<m;N<<=1);
Poly::Exp(N,f,b.f),clr(b.f+m,N-m);
return b;
}
};
}
Poly::Polyn<maxn> f,g;
int main(){
f.n=read<int>()+1;
g.n=read<int>()+1;
Poly::init(f.n+g.n-1);
for(int i=0;i<f.n;i++)
f[i]=read<int>();
for(int i=0;i<g.n;i++)
g[i]=read<int>();
f*=g;
for(int i=0;i<f.n;i++)
printf("%d ",f[i]);
return 0;
}
贴个老板子
namespace Modsqrt{
#define ll long long
ll w2;
struct CP{
ll x,y;
CP() {}
CP(ll x,ll y):x(x),y(y) {}
CP operator *(const CP &a) const{
ll X=(x*a.x+y*a.y%mod*w2)%mod;
ll Y=(x*a.y+y*a.x)%mod;
return CP(X,Y);
}
};
inline CP CP_qpow(CP a,int b){
CP ans=CP(1,0);
for(;b;b>>=1){
if(b&1)ans=ans*a;
a=a*a;
}
return ans;
}
inline ll modsqrt(ll x){
srand(time(0));
ll y=1ll*rand()*rand()%mod;
while(qpow(w2=(y*y+mod-x)%mod,(mod-1)>>1)==1)
y=1ll*rand()*rand()%mod;
CP ans=CP_qpow(CP(y,1),(mod+1)>>1);
return min(ans.x,mod-ans.x);
}
#undef ll
}
using namespace Modsqrt;
long long inv[maxn],frac[maxn],invf[maxn];
inline void Init_Inv(int N){
frac[0]=1;
for(int i=1;i<=N;i++)frac[i]=frac[i-1]*i%mod;
invf[N]=qpow(frac[N],mod-2);
for(int i=N;i>=1;i--)invf[i-1]=invf[i]*i%mod;
for(int i=1;i<=N;i++)inv[i]=invf[i]*frac[i-1]%mod;
}
inline void init(int N){
Init_Inv(N);
}
namespace Polyn{
#define G 3
#define ll long long
int lstn,rev[maxn];
long long g[2][33];
inline void cpy(int N,ll *a,ll *b){
for(int i=0;i<N;i++)a[i]=b[i];
}
inline void clr(int N,ll *a){
for(int i=0;i<N;i++)a[i]=0;
}
inline void mve(int N,int len,ll *a){
if(!len)return;
if(len>0){
for(int i=N-1;i>=len;i--)a[i]=a[i-len];
for(int i=len-1;i>=0;i--)a[i]=0;
}
else {
len=-len;
for(int i=0;i<N-len;i++)a[i]=a[i+len];
for(int i=N-len;i<N;i++)a[i]=0;
}
}
inline void Init_G(){
g[0][23]=qpow(G,(mod-1)/(1<<23));
g[1][23]=qpow(g[0][23],mod-2);
for(int i=22;i>=1;i--){
g[0][i]=g[0][i+1]*g[0][i+1]%mod;
g[1][i]=g[1][i+1]*g[1][i+1]%mod;
}
}
inline void init(int N){
if(lstn==N)return;
lstn=N;
for(int i=1;i<N;i++)
rev[i]=(rev[(i>>1)]>>1)|(i&1?(N>>1):0);
}
inline void Der(int N,ll *f){
for(int i=1;i<N;i++)
f[i-1]=f[i]*i%mod;
f[N-1]=0;
}
inline void Int(int N,ll *f){
for(int i=N;i;i--)
f[i]=f[i-1]*inv[i]%mod;
f[0]=0;
}
inline void NTT(int N,ll *f,bool flg){
for(int i=1;i<N;i++)
if(i<rev[i])swap(f[i],f[rev[i]]);
for(int i=1,lg=1;i<N;i<<=1,lg++){
for(int p=(i<<1),j=0;j<N;j+=p){
ll ng=1;
for(int k=0;k<i;k++){
ll val=ng*f[i+j+k]%mod;
f[i+j+k]=(f[j+k]+mod-val)%mod;
(f[j+k]+=val)%=mod;
(ng*=g[flg][lg])%=mod;
}
}
}
if(!flg)return;
ll invn=qpow(N,mod-2);
for(int i=0;i<N;i++)
(f[i]*=invn)%=mod;
}
inline void Mul(int n,ll *a,ll b){
for(int i=0;i<n;i++)(a[i]*=b)%=mod;
}
inline void Mul(int n,ll *a,ll *b,int na=-1,int nb=-1,int len=-1){
int N=1;
for(;N<n;N<<=1);
init(N);
if(na<0)na=n;
if(nb<0)nb=n;
clr(N-na,a+na),clr(N-nb,b+nb);
NTT(N,a,0),NTT(N,b,0);
for(int i=0;i<N;i++)
(a[i]*=b[i])%=mod;
NTT(N,a,1);
if(len<0)return;
clr(N-len,a+len);
}
inline void Inv(int n,ll *f,ll *ans){
static ll A[maxn],B[maxn];
int N=1;
for(;N<n;N<<=1);
clr(N,A),clr(N,B),clr(N,ans);
ans[0]=qpow(f[0],mod-2);
for(int len=2;len<=N;len<<=1){
cpy(len>>1,A,ans);
cpy(len,B,f);
Mul(len,A,B);
clr(len>>1,A);
cpy(len,B,ans);
Mul(len,A,B);
for(int i=(len>>1);i<len;i++)
ans[i]=(ans[i]*2+mod-A[i])%mod;
}
}
inline void Sqrt(int n,ll *f,ll *ans){
static ll A[maxn],B[maxn];
int N=1;
for(;N<n;N<<=1);
clr(N,A),clr(N,B),clr(N,ans);
ans[0]=modsqrt(f[0]);
for(int len=2;len<=N;len<<=1){
Inv(len,ans,A);
cpy(len,B,f);
Mul((len<<1),A,B,len,len,len);
for(int i=0;i<len;i++)
ans[i]=(ans[i]+A[i])*inv2%mod;
}
clr(N-n,ans+n);
}
inline void Ln(int n,ll *f,ll *ans){
static ll A[maxn];
int N=1;
for(;N<(n<<1);N<<=1);
clr(N,A),clr(N,ans);
cpy(n,ans,f);
Der(n,ans);
Inv(n,f,A);
Mul(n+n-1,ans,A,n);
Int(n,ans);
}
inline void Exp(int n,ll *f,ll *ans){
static ll A[maxn],B[maxn];
int N=1;
for(;N<n;N<<=1);
clr(N,A),clr(N,B),clr(N,ans);
ans[0]=1;
for(int len=2;len<=N;len<<=1){
cpy(len,B,f);
B[0]++;
Ln(len,ans,A);
for(int i=0;i<len;i++)
(B[i]+=mod-A[i])%=mod;
Mul((len<<1),ans,B,len,len,len);
}
clr(N-n,ans+n);
}
inline void Pow(int n,int k,int k1,int MOD,ll *f,ll *ans){
if(n==1)cpy(n,ans,f);
static ll A[maxn];
int x=0;
int N=1;
for(;N<n;N<<=1);
clr(N,A),clr(N,ans);
for(;x<n&&!f[x];x++);
if(1ll*x*k1>=MOD)return;
cpy(n,ans,f);
mve(n,-x,ans);
int m=MOD-x;
if(ans[0]>1){
ll inv0=qpow(ans[0],mod-2);
for(int i=0;i<n-x;i++)
(ans[i]*=inv0)%=mod;
}
Ln(m,ans,A);
Mul(m,A,k);
Exp(m,A,ans);
mve(MOD,x*k1,ans);
if(f[x]>1)Mul(MOD,ans,qpow(f[x],k1));
}
#undef ll
#undef G
}
long long A[maxn];
struct P{
#define ll long long
int n;
ll f[maxn];
inline void Read(){
for(int i=0;i<n;i++)
f[i]=read<ll>();
}
inline void Print(){
for(int i=0;i<n;i++)
printf("%lld ",f[i]);
puts("");
}
ll& operator [](const int &x){
return f[x];
}
inline P Mod(int N){
P c;
c.n=N;
for(int i=0;i<N;i++)
c[i]=f[i];
return c;
}
inline P R(){
P c;
c.n=n;
for(int i=0;i<n;i++)
c[i]=f[n-i-1];
return c;
}
inline P Der(){
P c;
c.n=n-1;
for(int i=1;i<n;i++)
c[i-1]=f[i]*i%mod;
return c;
}
inline P Int(){
P c;
c.n=n+1;
for(int i=1;i<=n;i++)
c[i]=f[i-1]*inv[i]%mod;
c[0]=0;
return c;
}
inline P Inv(){
P c;
c.n=n;
Polyn::Inv(n,f,c.f);
return c;
}
inline P Sqrt(){
P c;
c.n=n;
Polyn::Sqrt(n,f,c.f);
return c;
}
inline P Ln(){
P c;
c.n=n;
Polyn::Ln(n,f,c.f);
return c;
}
inline P Exp(){
P c;
c.n=n;
Polyn::Exp(n,f,c.f);
return c;
}
inline P Pow(int k,int k1,int MOD){
P c;
c.n=n;
Polyn::Pow(n,k,k1,MOD,f,c.f);
return c;
}
P operator -(){
P c;
c.n=n;
for(int i=0;i<c.n;i++)c[i]=mod-f[i];
return c;
}
P operator +(const ll b){
P c;
c.n=n;
for(int i=0;i<c.n;i++)c[i]=f[i];
(c[0]+=b)%=mod;
return c;
}
P operator +(P b){
P c;
c.n=max(n,b.n);
for(int i=0;i<c.n;i++)
c[i]=(f[i]+b[i])%mod;
return c;
}
P operator -(const ll b){
P c;
c.n=n;
for(int i=0;i<c.n;i++)c[i]=f[i];
(c[0]+=mod-b%mod)%=mod;
return c;
}
P operator -(P b){
P c;
c.n=max(n,b.n);
for(int i=0;i<c.n;i++)
c[i]=(f[i]+mod-b[i])%mod;
return c;
}
P operator *(const ll num){
P c;
c.n=n;
for(int i=0;i<n;i++)
c[i]=f[i]*num%mod;
return c;
}
P operator *(P b){
P c;
c.n=n+b.n-1;
for(int i=0;i<n;i++)c[i]=f[i];
for(int i=0;i<b.n;i++)A[i]=b[i];
int N=1;
for(;N<c.n;N<<=1);
for(int i=n;i<N;i++)c[i]=0;
for(int i=b.n;i<N;i++)A[i]=0;
Polyn::Mul(c.n,c.f,A);
return c;
}
#undef ll
};

浙公网安备 33010602011771号