这个题堪称 简易模板全家桶。
关于各个函数的实现,大多数都是利用牛顿迭代公式()+倍增。
以下为多项式全家桶证明:
下面的分别为已知多项式,当前所求多项式和上一个状态(规模小一半)的多项式.(简记)
由于.
所以的高位乘上在意义下为0.
所以与在当前等价.
即
对两边求导:.(链式反应)
积分即可得到.
因为为逆运算,所以可得:
设
则可得到:.
多项式带余除法.
.
已知求.为次多项式,为次多项式,的次数.
可以发现的系数为系数的翻转,我们简记这个多项式为.
则有:
我们可以发现.
这样求出后即可得到.
代码:
#include<ctime>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define gc getchar()//(p1==p2&&(p2=(p1=buf)+fread(buf,1,N,stdin),p1==p2)?EOF:*p1++)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int N=1<<22|10,mod=998244353;
char buf[N],*p1=buf,*p2=buf;
template<class o>void qr(o &x) {
char c=gc; x=0;
while(!isdigit(c))c=gc;
while(isdigit(c))x=(x*10+c-'0')%mod,c=gc;
}
template<class o>void qw(o x) {
if(x/10) qw(x/10);
putchar(x%10+'0');
}
template<class o>void pr1(o x) {qw(x); putchar(' ');}
template<class o>void pr2(o x) {qw(x); puts("");}
ll power(ll a,ll b=mod-2,ll p=mod) {
ll c=1;
while(b) {
if(b&1) c=c*a%p;
b /= 2; a=a*a%p;
}
return c;
}
namespace Cipolla {
ll p=mod,w;
struct CP {
ll x,y;
CP(ll a=1,ll b=0) {x=a; y=b;}
CP operator *(CP b) const {return CP( ((x*b.x+y*b.y%p*w)%p+p)%p , ((x*b.y+y*b.x)%p+p)%p);}
} ;
CP power(CP a,ll b=(p+1)/2) {
CP c;
while(b) {
if(b&1) c=c*a;
b /= 2; a=a*a;
}
return c;
}
bool pd(ll x) {return ::power(x,(p-1)/2,p)==p-1;}
ll solve(ll n) {
if(n<=1) return n;
ll a; do {
a=(rand()<<15|rand())%p;
w=((a*a-n)%p+p)%p;
} while(!pd(w));
ll x=power(CP(a,1)).x,y=p-x;
return min(x,y);
}
}
namespace P {
const int g=3,inv2=(mod+1)/2;
int R[N],w[N],Inv[N];
int calc(int x) {if((x&-x)==x) return x; int n=1; while(n<x) n*=2; return n;}//输入长度
void init(int m) {
int n=calc(m)*4;
Inv[1]=1; for(int i=2;i<n;i++) Inv[i]=(ll)Inv[mod%i]*(mod-mod/i)%mod;
for(int i=1;i<n;i*=2) {//枚举半区间长度,把对应的单位根填入w数组
ll t=power(g,(mod-1)/(2*i)),d=1;
for(int j=0;j<i;j++) w[i+j]=d,d=d*t%mod;
}
}
int pre(int m) {//输入总长度
int n=calc(m);
for(int i=1;i<n;i++) R[i]=(R[i>>1]>>1)|(i&1?n>>1:0);
return n;
}
void upd(int &x) {x+=x>>31&mod;}
void DFT(int *f,int n) {
static ull p[N];
for(int i=0;i<n;i++) p[R[i]]=f[i];
for(int i=1,t;i<n;i*=2) for(int j=0;j<n;j+=2*i)
for(int k=0;k<i;k++) t=p[j+k+i]*w[i+k]%mod,p[j+k+i]=p[j+k]+mod-t,p[j+k]+=t;
for(int i=0;i<n;i++) f[i]=p[i]%mod;
}
void IDFT(int *f,int n) {
reverse(f+1,f+n); DFT(f,n); ll inv=power(n);
for(int i=0;i<n;i++) f[i]=inv*f[i]%mod;
}
void copy(int *a,int *b,int n) {memcpy(a,b,sizeof(int[n]));}
void clear(int *a,int len) {memset(a+len,0,sizeof(int[len]));}
void clear(int *a,int x,int y) {if(x<y) memset(a+x,0,sizeof(int[y-x]));}
void dao(int *a,int *b,int n) {
for(int i=1;i<n;i++) b[i-1]=(ll)a[i]*i%mod;
b[n-1]=0;
}
void ji(int *a,int *b,int n) {
for(int i=n-1; i;i--) b[i]=(ll)a[i-1]*Inv[i]%mod;
b[0]=0;
}
void mult(int *a,int *b,int n,int m) {
static int c[N];
int x=pre(n+m);
clear(a,n,x); copy(c,b,m); clear(c,m,x);
DFT(a,x); DFT(c,x);
for(int i=0;i<x;i++) a[i]=(ll)a[i]*c[i]%mod;
IDFT(a,x);
}
int h[N];
void getinv(int *a,int *b,int n) {//
clear(b,0,2*n); clear(a,n); clear(h,0,2*n); b[0]=power(a[0]);
for(int p=2;p<=n;p*=2) {
int x=pre(p*2);
copy(h,a,p); clear(h,p); DFT(h,x); DFT(b,x);
for(int i=0;i<x;i++) b[i]=(ll)(2-(ll)b[i]*h[i]%mod+mod)*b[i]%mod;
IDFT(b,x); clear(b,p);
}
}
void getsqrt(int *a,int *b,int n) {
static int c[N],f[N];
clear(c,0,2*n); clear(f,0,2*n); clear(a,n); clear(b,0,2*n);
b[0]=Cipolla::solve(a[0]); b[1]=0;
for(int p=2;p<=n;p*=2) {
copy(f,a,p); clear(f,p); getinv(b,c,p); mult(f,c,p,p);
for(int i=0;i<p;i++) b[i]=(ll)(b[i]+f[i])*inv2%mod;
}
}
void getln(int *a,int *b,int n) {//
getinv(a,b,n); dao(a,h,n);
mult(h,b,n,n); ji(h,b,n); clear(h,0,2*n);
}
void getexp(int *a,int *b,int n) {
static int c[N]; clear(b,0,2*n); clear(a,n); b[0]=1;
for(int p=2;p<=n;p*=2) {
copy(c,b,p/2); clear(c,p/2); getln(c,b,p);upd(--b[0]);
for(int i=0;i<p;i++) upd(b[i]=-b[i]+a[i]);
mult(b,c,p,p); clear(b,p);
}
}
void getdiv(int *a,int *b,int *c,int n,int m) {//c=a(n)/b(m).
static int h1[N],h2[N];
int len=n-m+1,x=calc(len);
copy(h1,a,n); copy(h2,b,m);
clear(h1,n,x); clear(h2,m,x);
reverse(h1,h1+n); reverse(h2,h2+m);
getinv(h2,c,x); mult(c,h1,x,x); reverse(c,c+len); clear(c,len);
}
void getmod(int *a,int *b,int *c,int n,int m) {
static int d[N];
getdiv(a,b,c,n,m);
copy(d,b,m);mult(c,d,n-m+1,m);
for(int i=0;i<m;i++) upd(c[i]=a[i]-c[i]);
}
}
int n,m,t,f[N],g[N],h[N];
int main() {
qr(n); qr(m); n++; t=P::calc(n); P::init(t);
for(int i=0;i<n;i++) qr(f[i]);
P::getsqrt(f,g,t);
P::getinv(g,h,t);
P::ji(h,g,t);
P::getexp(g,h,t);
for(int i=0;i<t;i++) P::upd(g[i]=f[i]-h[i]);
P::upd(g[0]+=2); P::upd(g[0]-=f[0]);
P::getln(g,h,t); P::upd(h[0]+=1-mod);
P::getln(h,g,t); for(int i=0;i<t;i++) g[i]=(ll)g[i]*m%mod;
P::getexp(g,h,t); P::dao(h,f,n); n--;
for(int i=0;i<n;i++) pr1(f[i]);
return 0;
}