[COGS2189]帕秋莉的超級多項式(多項式全家桶)
阿新 • • 發佈:2018-12-09
Code
直接上模板全套就好辣!(跑得還挺快,17.33s,現在在rk10)
#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if (ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template <class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int mod=998244353,inv2=(mod+1)>>1;
namespace {
inline int Add(const int &x,const int &y) {
int res=x+y;
if(res>=mod)
res-=mod;
return res;
}
inline int Sub(const int &x,const int &y) {
int res=x-y;
if(res<0)
res+=mod;
return res;
}
inline int Mul(const int &x,const int &y) {
return 1ll*x*y%mod;
}
inline int Pow(int x,int y=mod-2) {
int res=1;
while(y) {
if(y&1)
res=1ll*res*x%mod;
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
}
const int fmaxn=18,Fmaxn=(1<<fmaxn)+5,G=3;
int nxtl[Fmaxn],nxtlim[Fmaxn],inv[Fmaxn];
namespace Poly {
static int root[fmaxn][Fmaxn],mx,rev[Fmaxn];
inline void Rev(int l) {
rev[0]=0;
for(int i=1;i<(1<<l);++i)
rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
}
inline void DFT(vector<int>&a,int bit) {
if(mx<bit) {
for(int i=mx;i<bit;++i) {
int len=1<<i,w0=Pow(G,(mod-1)/(len<<1)),w=1;
for(int j=0;j<len;++j)
root[i][j]=w,w=Mul(w,w0);
}
mx=bit;
}
for(int i=1;i<1<<bit;++i)
if(i<rev[i])
swap(a[i],a[rev[i]]);
for(int i=0,len=1;i<bit;++i,len<<=1)
for(int j=0;j<(1<<bit);j+=(len<<1))
for(int k=0;k<len;++k) {
int x=a[j+k],y=Mul(a[j+k+len],root[i][k]);
a[j+k]=Add(x,y),a[j+k+len]=Sub(x,y);
}
}
inline void IDFT(vector<int>&a,int bit) {
int len=(1<<bit),inv=Pow(len);
reverse(a.begin()+1,a.end());
DFT(a,bit);
for(int i=0;i<len;++i)
a[i]=Mul(a[i],inv);
}
inline void FFT(vector<int>a,vector<int>b,vector<int>&c) {
int la=a.size(),lb=b.size(),lc=la+lb-1,l=nxtl[lc],lim=nxtlim[lc];
a.resize(lim),b.resize(lim),c.resize(lim);
Rev(l),DFT(a,l),DFT(b,l);
for(int i=0;i<lim;++i)
c[i]=Mul(a[i],b[i]);
IDFT(c,l);
c.resize(lc);
}
inline void Inv(vector<int>f,vector<int>&g,int len) {
int lim=nxtlim[len];
f.resize(lim),g.resize(lim);
g[0]=Pow(f[0]);
for(int i=2,p=1;i<=lim;i<<=1,++p) {
vector<int>h(i<<1),l(i<<1),o(i<<1);
for(int j=0;j<i;++j)
h[j]=f[j];
for(int j=0;j<i>>1;++j)
l[j]=g[j];
Rev(p+1),DFT(h,p+1),DFT(l,p+1);
for(int j=0;j<i<<1;++j)
o[j]=Mul(h[j],Mul(l[j],l[j]));
IDFT(o,p+1);
for(int j=0;j<i;++j)
g[j]=Sub(Mul(2,g[j]),o[j]);
}
g.resize(len);
}
inline void Ln(vector<int>f,vector<int>&g,int len) {
vector<int>h(len,0);
for(int i=1;i<len;++i)
h[i-1]=Mul(f[i],i);
h[len-1]=0;
Inv(f,g,len);
FFT(g,h,g);
for(int i=len-1;i;--i)
g[i]=Mul(g[i-1],::inv[i]);
g[0]=0;
g.resize(len);
}
inline void Exp(vector<int>f,vector<int>&g,int len,int init) {
int lim=nxtlim[len];
f.resize(lim),g.resize(lim);
if(init)
g[0]=1;
for(int i=2,p=1;i<=lim;i<<=1,++p) {
vector<int>h(i<<1),l,o(i<<1,0);
for(int j=0;j<i>>1;++j)
h[j]=g[j];
Ln(h,l,i);
for(int j=0;j<i;++j)
l[j]=Sub(f[j]+(!j),l[j]),l.push_back(0);
Rev(p+1),DFT(h,p+1),DFT(l,p+1);
for(int j=0;j<i<<1;++j)
o[j]=Mul(h[j],l[j]);
IDFT(o,p+1);
for(int j=0;j<i;++j)
g[j]=o[j];
}
g.resize(len);
}
inline void Pow(vector<int>f,vector<int>&g,int len,ll k) {
vector<int>h;
Ln(f,h,len);
int o=k%mod;
for(int i=0;i<len;++i)
h[i]=Mul(h[i],o);
g.push_back(::Pow(f[0],(int)(k%(mod-1))));
Exp(h,g,len,0);
}
inline void Sqrt(vector<int>f,vector<int>&g,int len) {
g.push_back((int)sqrt(f[0]));
int lim=nxtlim[len];
for(int i=2,p=1;i<=lim;i<<=1,++p) {
vector<int>h(i),l,o(i<<1,0);
g.resize(i<<1);
for(int j=0;j<i;++j)
h[j]=g[j];
Inv(h,l,i);
l.resize(i<<1);
for(int j=0;j<min(i,(int)f.size());++j)
o[j]=f[j];
Rev(p+1),DFT(g,p+1),DFT(l,p+1),DFT(o,p+1);
for(int j=0;j<i<<1;++j)
o[j]=Mul(Add(g[j],Mul(l[j],o[j])),inv2);
IDFT(o,p+1);
for(int j=0;j<i;++j)
g[j]=o[j];
g.resize(i);
}
g.resize(len);
}
}
vector<int>a,b,c;
int n,m;
inline void Getmul() {
a.clear(),b.clear();
read(n),read(m);
for(int i=0,x;i<=n;++i)
read(x),a.push_back(x);
for(int i=0,x;i<=m;++i)
read(x),b.push_back(x);
Poly::FFT(a,b,c);
for(int i=0;i<(int)c.size();++i)
printf("%d ",c[i]);
}
inline void Getinv() {
a.clear();
read(n);
for(int i=0,x;i<n;++i)
read(x),a.push_back(x);
Poly::Inv(a,b,n);
for(int i=0;i<n;++i)
printf("%d ",b[i]);
}
inline void Getln() {
a.clear();
read(n);
for(int i=0,x;i<n;++i)
read(x),a.push_back(x);
Poly::Ln(a,b,n);
for(int i=0;i<n;++i)
printf("%d ",b[i]);
}
inline void Getexp() {
a.clear();
read(n);
for(int i=0,x;i<n;++i)
read(x),a.push_back(x);
Poly::Exp(a,b,n,1);
for(int i=0;i<n;++i)
printf("%d ",b[i]);
}
inline void Getpow() {
a.clear();ll p;
read(n),read(p);
for(int i=0,x;i<n;++i)
read(x),a.push_back(x);
Poly::Pow(a,b,n,p);
for(int i=0;i<n;++i)
printf("%d ",b[i]);
}
inline void Getsqrt() {
a.clear();
read(n);
for(int i=0,x;i<n;++i)
read(x),a.push_back(x);
Poly::Sqrt(a,b,n);
for(int i=0;i<n;++i)
printf("%d ",b[i]);
}
int main() {
freopen("polynomial.in","r",stdin);
freopen("polynomial.out","w",stdout);
nxtl[1]=0,nxtlim[1]=1,inv[1]=1;
for(int i=1;i<Fmaxn-1;++i) {
nxtl[i+1]=nxtl[i],nxtlim[i+1]=nxtlim[i];
if(i==(i&-i))
++nxtl[i+1],nxtlim[i+1]<<=1;
}
for(int i=2;i<Fmaxn;++i)
inv[i]=Mul(inv[mod%i],(mod-mod/i));
// Getmul();
// Getinv();
// Getln();
// Getexp();
// Getpow();
// Getsqrt();
read(n);ll p;read(p);
for(int i=0,x;i<n;++i)
read(x),a.push_back(x);
Poly::Sqrt(a,b,n);
Poly::Inv(b,c,n);
for(int i=n-1;i;--i)
c[i]=Mul(c[i-1],inv[i]);
c[0]=0;
b.clear();
Poly::Exp(c,b,n,1);
c.clear();
Poly::Inv(b,c,n);
++c[0];
b.clear();
Poly::Ln(c,b,n);
++b[0];
c.clear();
Poly::Pow(b,c,n,p);
for(int i=1;i<n;++i)
c[i-1]=Mul(c[i],i);
c[n-1]=0;
for(int i=0;i<n;++i)
printf("%d ",c[i]);
puts("");
return 0;
}