博主太菜惹。。。只放模板。。。
\(FFT\)
#include<bits/stdc++.h>
#define IL inline
#define LF double
using namespace std;
const int N=4e6+3;
const LF Pi=acos(-1.0);
int n,m,lim=1,cnt,r[N],tp;
struct comp{
LF x,y;
comp(LF xx=0,LF yy=0){x=xx,y=yy;}
IL comp operator+(const comp &a) const{return comp(x+a.x,y+a.y);}
IL comp operator-(const comp &a) const{return comp(x-a.x,y-a.y);}
IL comp operator*(const comp &a) const{return comp(x*a.x-y*a.y,x*a.y+y*a.x);}
}a[N],b[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
void FFT(comp *a,int op){
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
comp wn(cos(Pi/i),op*sin(Pi/i));
for(int j=0;j<lim;j+=i<<1){
comp w(1,0);
for(int k=0;k<i;++k,w=w*wn){
comp x=a[j+k],y=w*a[j+i+k];
a[j+k]=x+y,a[j+i+k]=x-y;
}
}
}
if(op==-1) for(int i=0;i<lim;++i) a[i].x=a[i].x/lim;
}
int main()
{
n=in()+1,m=in()+1;
while(lim<n+m) lim<<=1,++cnt;
for(int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)<<cnt-1);
for(int i=0;i<n;++i) a[i].x=in();
for(int i=0;i<m;++i) b[i].x=in();
FFT(a,1),FFT(b,1);
for(int i=0;i<lim;++i) a[i]=a[i]*b[i];
FFT(a,-1);
for(int i=0;i<n+m-1;++i) printf("%d ",(int)(a[i].x/lim+0.5));
return 0;
}
\(NTT\)
#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=4e6+3,p=998244353,G=3,Gi=332748118;
int n,m,a[N],b[N],r[N],lim=1,cnt,inv;
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL int ksm(int a,int b){
int c=1;
while(b){
if(b&1) c=1ll*c*a%p;
a=1ll*a*a%p,b>>=1;
}
return c;
}
void NTT(int *a,int op){
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
int wn=ksm(op?G:Gi,(p-1)/(i<<1));
for(int j=0;j<lim;j+=(i<<1)){
int w=1;
for(int k=0;k<i;++k,w=1ll*w*wn%p){
int x=a[j+k],y=1ll*w*a[j+i+k]%p;
a[j+k]=(x+y)%p,a[j+i+k]=(x-y+p)%p;
}
}
}
}
int main()
{
n=in()+1,m=in()+1;
for(int i=0;i<n;++i) a[i]=in();
for(int i=0;i<m;++i) b[i]=in();
while(lim<n+m) lim<<=1,++cnt;
for(int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)<<cnt-1);
NTT(a,1),NTT(b,1);
for(int i=0;i<lim;++i) a[i]=1ll*a[i]*b[i]%p;
NTT(a,0),inv=ksm(lim,p-2);
for(int i=0;i<n+m-1;++i) printf("%lld ",1ll*a[i]*inv%p);
return 0;
}
多项式求逆
#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define re register
using namespace std;
const int N=4e5+3,p=998244353,G=3,Gi=332748118;
int n,r[N],lim=1,op,cnt,bas;
LL a[N],b[N],c[N],d[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
re int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL LL ksm(re LL a,re LL b){
re LL c=1;
while(b){
if(b&1) c=c*a%p;
a=a*a%p,b>>=1;
}
return c;
}
IL LL mod(LL x){return x>=p?x-p:x;}
IL void calc(int lim){
for(re int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
IL void NTT(LL *a,int op){
for(re int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(re int i=1;i<lim;i<<=1){
LL wn=ksm(~op?G:Gi,(p-1)/(i<<1));
for(re int j=0;j<lim;j+=(i<<1)){
LL w=1;
for(re int k=0;k<i;++k,w=w*wn%p){
LL x=a[j+k],y=w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
LL inv=ksm(lim,p-2);
for(re int i=0;i<lim;++i) a[i]=a[i]*inv%p;
}
}
void solve(LL *a,LL *b,int n){
if(n==1){b[0]=ksm(a[0],p-2);return;}
solve(a,b,n+1>>1);lim=1;
while(lim<(n<<1)) lim<<=1;calc(lim);
memcpy(c,a,8*n),memset(c+n,0,8*(lim-n));
NTT(c,1),NTT(b,1);
for(re int i=0;i<lim;++i) b[i]=mod(2+p-b[i]*c[i]%p)*b[i]%p;
NTT(b,-1),memset(b+n,0,8*(lim-n));
}
int main()
{
n=in();
for(re int i=0;i<n;++i) a[i]=in();
solve(a,b,n);
for(re int i=0;i<n;++i) printf("%lld ",b[i]);
return 0;
}
多项式除法
#include<bits/stdc++.h>
#define IL inline
#define LL long long
#define re register
using namespace std;
const int N=4e5+3,p=998244353,G=3,Gi=332748118;
int n,m,K,lim,r[N];
LL f[N],fr[N],g[N],gr[N],gv[N],q[N],R[N],a[N],b[N],c[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
re int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL LL ksm(re LL a,re LL b){
re LL c=1;
while(b){
if(b&1) c=c*a%p;
a=a*a%p,b>>=1;
}
return c;
}
IL LL mod(LL x){return x>=p?x-p:x;}
IL void calcrev(int lim){
for(re int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
void init(){
n=in()+1,m=in()+1,K=n-m+1;
for(re int i=0;i<n;++i) f[i]=fr[i]=in();
for(re int i=0;i<m;++i) g[i]=gr[i]=in();
reverse(fr,fr+n),reverse(gr,gr+m);
}
IL void NTT(LL *a,int lim,int op){
for(re int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(re int i=1;i<lim;i<<=1){
re LL wn=ksm(~op?G:Gi,(p-1)/(i<<1));
for(re int j=0;j<lim;j+=(i<<1)){
re LL w=1;
for(re int k=0;k<i;++k,w=w*wn%p){
LL x=a[j+k],y=w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
LL inv=ksm(lim,p-2);
for(re int i=0;i<lim;++i) a[i]=a[i]*inv%p;
}
}
void get_inv(LL *a,LL *b,int n){
if(n==1){b[0]=ksm(a[0],p-2);return;}
get_inv(a,b,n+1>>1);
lim=1;while(lim<(n<<1)) lim<<=1;calcrev(lim);
memcpy(c,a,8*n),memset(c+n,0,8*(lim-n));
NTT(c,lim,1),NTT(b,lim,1);
for(re int i=0;i<lim;++i) b[i]=mod(2-b[i]*c[i]%p+p)*b[i]%p;
NTT(b,lim,-1),memset(b+n,0,8*(lim-n));
}
IL void mul(LL *a,LL *b,int n,int m){
lim=1;while(lim<n+m) lim<<=1;calcrev(lim);
memcpy(c,b,8*m),memset(c+m,0,8*(lim-m)),memset(a+n,0,8*(lim-n));
NTT(a,lim,1),NTT(c,lim,1);
for(int i=0;i<lim;++i) a[i]=c[i]*a[i]%p;
NTT(a,lim,-1);
}
void divid(){
get_inv(gr,gv,K);
memcpy(q,fr,8*n);
mul(q,gv,n,K);
reverse(q,q+K);
mul(g,q,m,K);
for(re int i=0;i<m-1;++i) R[i]=mod(f[i]-g[i]+p);
for(re int i=0;i<K;++i) printf("%lld ",q[i]);printf("\n");
for(re int i=0;i<m-1;++i) printf("%lld ",R[i]);
}
int main()
{
init();
divid();
return 0;
}
多项式对数函数
#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=4e5+3,p=998244353,G=3,Gi=332748118;
int n,lim=1,r[N];
LL a[N],b[N],c[N],f[N],g[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL LL mod(LL x){return x>=p?x-p:x;}
IL LL ksm(LL a,LL b){
LL c=1;
while(b){
if(b&1) c=c*a%p;
a=a*a%p,b>>=1;
}
return c;
}
IL void calc(int lim){
for(int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
void NTT(LL *a,int lim,int op){
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
LL wn=ksm(~op?G:Gi,(p-1)/(i<<1));
for(int j=0;j<lim;j+=i<<1){
LL w=1;
for(int k=0;k<i;++k,w=w*wn%p){
LL x=a[j+k],y=w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
LL inv=ksm(lim,p-2);
for(int i=0;i<lim;++i) a[i]=a[i]*inv%p;
}
}
void get_inv(LL *a,LL *b,int n){
if(n==1){b[0]=ksm(a[0],p-2);return;}
get_inv(a,b,n+1>>1);
lim=1;while(lim<2*n) lim<<=1;calc(lim);
memcpy(c,a,8*n),memset(c+n,0,8*(lim-n));
NTT(c,lim,1),NTT(b,lim,1);
for(int i=0;i<lim;++i) b[i]=mod(2-c[i]*b[i]%p+p)*b[i]%p;
NTT(b,lim,-1),memset(b+n,0,8*(lim-n));
}
IL void get_dao(LL *a,LL *b,int n){for(int i=0;i<n-1;++i) b[i]=(i+1)*a[i+1]%p;b[n-1]=0;}
IL void jifen(LL *a,LL *b,int n){for(int i=1;i<n;++i) b[i]=a[i-1]*ksm(i,p-2)%p;b[0]=0;}
IL void get_ln(LL *f,LL *g,int n){
get_dao(f,a,n),get_inv(f,b,n);
lim=1;while(lim<2*n) lim<<=1;calc(lim);
NTT(a,lim,1),NTT(b,lim,1);
for(int i=0;i<lim;++i) a[i]=a[i]*b[i]%p;
NTT(a,lim,-1),jifen(a,g,n);
}
int main()
{
n=in();
for(int i=0;i<n;++i) f[i]=in();
get_ln(f,g,n);
for(int i=0;i<n;++i) printf("%lld ",g[i]);
return 0;
}
多项式 \(exp\)
#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=4e6+3,p=998244353,G=3,Gi=332748118;
int n,a[N],b[N],c[N],d[N],_a[N],_b[N],_c[N],_d[N],r[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL int mod(int x){return x>=p?x-p:x;}
IL int ksm(int a,int b){
int c=1;
while(b){
if(b&1) c=1ll*c*a%p;
a=1ll*a*a%p,b>>=1;
}
return c;
}
IL void calc(int lim){
for(int i=0;i<lim;++i)
r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
IL void NTT(int *a,int lim,int op){
calc(lim);
for(int i=0;i<lim;++i)
if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
int wn=ksm(~op?G:Gi,(p-1)/(i<<1));
for(int j=0;j<lim;j+=i<<1){
int w=1;
for(int k=0;k<i;++k,w=1ll*w*wn%p){
int x=a[j+k],y=1ll*w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
int inv=ksm(lim,p-2);
for(int i=0;i<lim;++i) a[i]=1ll*a[i]*inv%p;
}
}
IL void mul(int *a,int *b,int *c,int n,int m){
int lim=1,_a[N],_b[N];
while(lim<n+m-1) lim<<=1;
memcpy(_a,a,4*n),memcpy(_b,b,4*m),
memset(_a+n,0,4*(lim-n)),memset(_b+m,0,4*(lim-m));
NTT(_a,lim,1),NTT(_b,lim,1);
for(int i=0;i<lim;++i) c[i]=1ll*_a[i]*_b[i]%p;
NTT(c,lim,-1);
}
IL void get_inv(int *a,int *b,int n){
if(n==1){b[0]=ksm(a[0],p-2);b[1]=0;return;}
get_inv(a,b,n+1>>1);
int lim=1;
while(lim<2*n-1) lim<<=1;
memcpy(c,a,4*n),memset(c+n,0,4*(lim-n)),
memset(b+n,0,4*(lim-n));
NTT(b,lim,1),NTT(c,lim,1);
for(int i=0;i<lim;++i) b[i]=1ll*mod(2-1ll*b[i]*c[i]%p+p)*b[i]%p;
NTT(b,lim,-1),memset(b+n,0,4*(lim-n));
}
IL void dao(int *a,int *b,int n){for(int i=1;i<n-1;++i) b[i-1]=1ll*a[i]*i%p;b[n-1]=0;}
IL void jifen(int *a,int *b,int n){for(int i=n-1;i;--i) b[i]=1ll*a[i-1]*ksm(i,p-2)%p;b[0]=0;}
IL void get_ln(int *a,int *b,int n){
int c[N],d[N];
get_inv(a,c,n),dao(a,d,n),
mul(c,d,c,n,n),jifen(c,b,n);
}
void get_exp(int *a,int *b,int n){
if(n==1){b[0]=1;b[1]=0;return;}
get_exp(a,b,n+1>>1);
int lim=1;
while(lim<2*n-1) lim<<=1;
get_ln(b,c,n),memset(c+n,0,4*(lim-n)),memset(b+n,0,4*(lim-n));
for(int i=0;i<n;++i) c[i]=mod(a[i]-c[i]+p);
c[0]=mod(c[0]+1);
mul(b,c,b,n,n);memset(b+n,0,4*(lim-n));
}
int main()
{
n=in();
for(int i=0;i<n;++i) a[i]=in();
get_exp(a,b,n);
for(int i=0;i<n;++i) printf("%d ",b[i]);
return 0;
}
多项式开根
#include<bits/stdc++.h>
#define IL inline
#define LL long long
using namespace std;
const int N=4e5+3,p=998244353,G=3,Gi=332748118;
int n,m,a[N],b[N],r[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL int ksm(int a,int b){
int c=1;
while(b){
if(b&1) c=1ll*c*a%p;
a=1ll*a*a%p,b>>=1;
}
return c;
}
IL int mod(int x){return x>=p?x-p:x;}
IL void calc(int lim){
for(int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
void NTT(int *a,int lim,int op){
calc(lim);
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
int wn=ksm(op>0?G:Gi,(p-1)/(i<<1));
for(int j=0;j<lim;j+=i<<1){
int w=1;
for(int k=0;k<i;++k,w=1ll*w*wn%p){
int x=a[j+k],y=1ll*w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
int inv=ksm(lim,p-2);
for(int i=0;i<lim;++i) a[i]=1ll*a[i]*inv%p;
}
}
void get_inv(int *a,int *b,int n){
if(n==1){b[0]=ksm(a[0],p-2);b[1]=0;return;}
get_inv(a,b,n+1>>1);
int lim=1,c[N];
while(lim<2*n) lim<<=1;
memcpy(c,a,4*n),memset(c+n,0,4*(lim-n));
memset(b+n,0,4*(lim-n));
NTT(c,lim,1),NTT(b,lim,1);
for(int i=0;i<lim;++i) b[i]=1ll*mod(2-1ll*c[i]*b[i]%p+p)*b[i]%p;
NTT(b,lim,-1);memset(b+n,0,4*(lim-n));
}
void mul(int *a,int *b,int *c,int n,int m){
int lim=1,_a[N],_b[N];
while(lim<n+m) lim<<=1;
memcpy(_a,a,4*n),memcpy(_b,b,4*m),
memset(_a+n,0,4*(lim-n)),memset(_b+m,0,4*(lim-m));
NTT(_a,lim,1),NTT(_b,lim,1);
for(int i=0;i<lim;++i) _a[i]=1ll*_a[i]*_b[i]%p;
NTT(_a,lim,-1);memcpy(c,_a,4*lim);
}
void get_sqrt(int *a,int *b,int n){
if(n==1){b[0]=1;return;}
get_sqrt(a,b,n+1>>1);
int lim=1,c[N],d[N],e[N];
while(lim<2*n) lim<<=1;
for(int i=0;i<n;++i) d[i]=mod(2*b[i]);
get_inv(d,e,n),memset(e+n,0,4*(lim-n));
mul(b,b,c,n,n),memset(c+n,0,4*(lim-n));
for(int i=0;i<n;++i) c[i]=mod(c[i]+a[i]);
mul(c,e,b,n,n),memset(b+n,0,4*(lim-n));
}
int main()
{
n=in();
for(int i=0;i<n;++i) a[i]=in();
get_sqrt(a,b,n);
for(int i=0;i<n;++i) printf("%d ",b[i]);puts("");
return 0;
}
多项式快速幂
#include<bits/stdc++.h>
#define IL inline
using namespace std;
const int N=4e5+4,p=998244353,G=3,Gi=332748118;
int n,m,k,a[N],b[N],d[N],r[N],inv[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL int mod(int x){return x>=p?x-p:x;}
IL int ksm(int a,int b){
int c=1;
while(b){
if(b&1) c=1ll*c*a%p;
a=1ll*a*a%p,b>>=1;
}
return c;
}
IL void calc(int lim){
for(int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
void pre(int n){
inv[0]=inv[1]=1;
for(int i=2;i<n;++i)
inv[i]=1ll*(p-p/i)*inv[p%i]%p;
}
void NTT(int *a,int lim,int op){
calc(lim);
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
int wn=ksm(op>0?G:Gi,(p-1)/(i<<1));
for(int j=0;j<lim;j+=i<<1){
int w=1;
for(int k=0;k<i;++k,w=1ll*w*wn%p){
int x=a[j+k],y=1ll*w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
int inv=ksm(lim,p-2);
for(int i=0;i<lim;++i) a[i]=1ll*a[i]*inv%p;
}
}
void get_inv(int *a,int *b,int n){
if(n==1){b[0]=ksm(a[0],p-2),b[1]=0;return;}
get_inv(a,b,n+1>>1);int lim=1,c[N];
while(lim<2*n) lim<<=1;
memcpy(c,a,4*n),memset(c+n,0,4*(lim-n)),
memset(b+n,0,4*(lim-n));
NTT(b,lim,1),NTT(c,lim,1);
for(int i=0;i<lim;++i) b[i]=1ll*mod(2-1ll*b[i]*c[i]%p+p)*b[i]%p;
NTT(b,lim,-1),memset(b+n,0,4*(lim-n));
}
void dao(int *a,int *b,int n){for(int i=0;i<n-1;++i) b[i]=1ll*(i+1)*a[i+1]%p;b[n-1]=0;}
void jifen(int *a,int *b,int n){for(int i=n-1;i;--i) b[i]=1ll*a[i-1]*inv[i]%p;b[0]=0;}
void get_ln(int *a,int *b,int n){
int c[N],d[N],lim=1;
while(lim<2*n) lim<<=1;
get_inv(a,c,n),dao(a,d,n);
memset(c+n,0,4*(lim-n)),memset(d+n,0,4*(lim-n));
NTT(c,lim,1),NTT(d,lim,1);
for(int i=0;i<lim;++i) c[i]=1ll*c[i]*d[i]%p;
NTT(c,lim,-1),jifen(c,b,n);
}
void get_exp(int *a,int *b,int n){
if(n==1){b[0]=1;return;}
get_exp(a,b,n+1>>1);
int c[N],d[N],lim=1;
while(lim<2*n) lim<<=1;
get_ln(b,c,n),get_ln(a,d,n);
for(int i=0;i<n;++i) d[i]=1ll*k*d[i]%p;
d[0]=(1-c[0]+d[0]+p)%p;
for(int i=1;i<n;++i) d[i]=mod(d[i]-c[i]+p);
memset(d+n,0,4*(lim-n));
NTT(d,lim,1),NTT(b,lim,1);
for(int i=0;i<lim;++i) b[i]=1ll*b[i]*d[i]%p;
NTT(b,lim,-1);memset(b+n,0,4*(lim-n));
}
int main()
{
char c;
n=in();
while((c=getchar())<'0'||c>'9');
k=c-'0';
while((c=getchar())>='0'&&c<='9')
k=(10ll*k+c-'0')%p;
for(int i=0;i<n;++i) a[i]=in();
pre(n);
get_exp(a,b,n);
for(int i=0;i<n;++i) printf("%d ",b[i]);putchar('\n');
return 0;
}
\(MTT\)
#include<bits/stdc++.h>
#define IL inline
#define LF long double
#define LL long long
using namespace std;
const LF Pi=acos(-1.0);
const int N=5e5+3,mod=32000;
int n,m,p,r[N];
LL ans[N];
struct com{
LF x,y;
com operator+(const com a) const{
return (com){x+a.x,y+a.y};}
com operator-(const com a) const{
return (com){x-a.x,y-a.y};}
com operator*(const com a) const{
return (com){x*a.x-y*a.y,x*a.y+y*a.x};}
com operator/(const LF a) const{
return (com){x/a,y/a};}
}t1[N],t2[N],q[N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL void calc(int lim){
for(int i=0;i<lim;++i) r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
IL LL get(LF x){return floor(x+0.5);}
void FFT(com *a,int lim,int op){
calc(lim);
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
com wn=(com){cos(Pi/i),op*sin(Pi/i)};
for(int j=0;j<lim;j+=i<<1){
com w=(com){1,0};
for(int k=0;k<i;++k,w=w*wn){
com x=a[j+k],y=w*a[j+i+k];
a[j+k]=x+y,a[j+i+k]=x-y;
}
}
}
}
int main()
{
int x,lim=1;
n=in()+1,m=in()+1,p=in();
while(lim<n+m) lim<<=1;
for(int i=0;i<n;++i){
x=in();
t1[i]=(com){x/mod,x%mod},
t2[i]=(com){x/mod,-x%mod};
}
for(int i=0;i<m;++i){
x=in();
q[i]=(com){x/mod,x%mod};
}
FFT(t1,lim,1),FFT(t2,lim,1),FFT(q,lim,1);
for(int i=0;i<lim;++i) q[i]=q[i]/lim;
for(int i=0;i<lim;++i) t1[i]=t1[i]*q[i];
for(int i=0;i<lim;++i) t2[i]=t2[i]*q[i];
FFT(t1,lim,-1),FFT(t2,lim,-1);
for(int i=0;i<n+m-1;++i){
LL a1b1,a2b2,a1b2,a2b1;
a1b1=get((t1[i].x+t2[i].x)/2)%p;
a1b2=get((t1[i].y+t2[i].y)/2)%p;
a2b1=get(t1[i].y-a1b2)%p;
a2b2=get(t2[i].x-a1b1)%p;
ans[i]=((a1b1*mod%p+(a1b2+a2b1)%p)*mod%p+a2b2)%p;
}
for(int i=0;i<n+m-1;++i) printf("%lld ",ans[i]);puts("");
return 0;
}
常系数齐次线性递推
#include<bits/stdc++.h>
#define IL inline
using namespace std;
const int N=15e4+3,p=998244353,G=3,Gi=332748118;
int n,m,a[N],b[N],c[N],f[N],v[N],r[N],Inv[N],Id[N],lim=1,ans,Wn[3][N];
IL int in(){
char c;int f=1;
while((c=getchar())<'0'||c>'9')
if(c=='-') f=-1;
int x=c-'0';
while((c=getchar())>='0'&&c<='9')
x=x*10+c-'0';
return x*f;
}
IL int mod(int x){return x>=p?x-p:x;}
IL int ksm(int a,int b){
int c=1;
while(b){
if(b&1) c=1ll*c*a%p;
a=1ll*a*a%p,b>>=1;
}
return c;
}
IL void calc(int lim){
for(int i=0;i<lim;++i)
r[i]=(r[i>>1]>>1)|((i&1)*(lim>>1));
}
void NTT(int *a,int lim,int op){
for(int i=0;i<lim;++i) if(i<r[i]) swap(a[i],a[r[i]]);
for(int i=1;i<lim;i<<=1){
int wn=Wn[op+1][i];
for(int j=0;j<lim;j+=i<<1){
int w=1;
for(int k=0;k<i;++k,w=1ll*w*wn%p){
int x=a[j+k],y=1ll*w*a[j+i+k]%p;
a[j+k]=mod(x+y),a[j+i+k]=mod(x-y+p);
}
}
}
if(op==-1){
int inv=ksm(lim,p-2);
for(int i=0;i<lim;++i) a[i]=1ll*a[i]*inv%p;
}
}
void get_inv(int *a,int *b,int n){
if(n==1){b[0]=ksm(a[0],p-2);b[1]=0;return;}
get_inv(a,b,n+1>>1);
int c[N],lim=1;
while(lim<n+n) lim<<=1;calc(lim);
memcpy(c,a,4*n),memset(c+n,0,4*(lim-n)),
memset(b+n,0,4*(lim-n));
NTT(c,lim,1),NTT(b,lim,1);
for(int i=0;i<lim;++i) b[i]=1ll*mod(2-1ll*c[i]*b[i]%p+p)*b[i]%p;
NTT(b,lim,-1);memset(b+n,0,4*(lim-n));
}
void mul(int *a,int *b,int *c,int n,int m){
int _a[N],_b[N],lim=1;
while(lim<n+m) lim<<=1;calc(lim);
memcpy(_a,a,4*n),memcpy(_b,b,4*m),
memset(_a+n,0,4*(lim-n)),memset(_b+m,0,4*(lim-m));
NTT(_a,lim,1),NTT(_b,lim,1);
for(int i=0;i<lim;++i) _a[i]=1ll*_a[i]*_b[i]%p;
NTT(_a,lim,-1);memcpy(c,_a,4*lim);
}
void Mod(int *a,int n){
int k=n-m,b[N],c[N];
memcpy(c,a,4*n);
reverse(c,c+n);
mul(c,Inv,b,n,m+1);
reverse(b,b+k);
mul(b,Id,c,k,m+1);
for(int i=0;i<n;++i) a[i]=mod(a[i]-c[i]+p);
}
int main()
{
while(lim<7e4)
Wn[2][lim]=ksm(G,(p-1)/(lim<<1)),
Wn[0][lim]=ksm(Gi,(p-1)/(lim<<1)),
lim<<=1;
n=in(),m=in();
for(int i=0;i<m;++i) f[i]=mod(p-in());
reverse(f,f+m),f[m]=1;
memcpy(Id,f,4*(m+1));
reverse(Id,Id+m+1);
get_inv(Id,Inv,m+1);
reverse(Id,Id+m+1);
for(int i=0;i<m;++i) v[i]=mod(in()+p);
a[1]=1,c[0]=1;
lim=1;
while(lim<2*m) lim<<=1;
while(n){
if(n&1) mul(c,a,c,m,m),Mod(c,lim);
n>>=1,mul(a,a,a,m,m),Mod(a,lim);
}
for(int i=0;i<m;++i) ans=mod(ans+1ll*c[i]*v[i]%p);
printf("%d\n",ans);
return 0;
}