版权声明:这是蒟蒻的BLOG,神犇转载也要吱一声哦~ https://blog.csdn.net/Dream_Lolita/article/details/88993169
【题目】
LOJ
给定
次多项式
,求
满足:
运算在模
下进行,保证常数项有二次剩余,
保留常数项较小的一个。
【解题思路】
差不多是最全的板子了。
除了没有写毛爷爷
以外可以适用几乎所有多项式题了吧。
板子额外补充了题里面没有的多项式除法。
复杂度常数极大的
【参考代码】
#include<bits/stdc++.h>
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=262333,mod=998244353,G=3;
namespace IO
{
int read()
{
int ret=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) ret=ret*10+(c^48),c=getchar();
return ret;
}
void write(int x){if(x>9)write(x/10);putchar(x%10^48);}
void writesp(int x){write(x);putchar(' ');}
}
using namespace IO;
namespace Math
{
int inv[N];
void gmin(int &x,int y){x=min(x,y);}
void gmax(int &x,int y){x=max(x,y);}
int upm(int x){return x>=mod?x-mod:(x<0?x+mod:x);}
void up(int &x,int y){x=upm(x+y);}
int mul(int x,int y){return 1ll*x*y%mod;}
int qpow(int x,int y){int res=1;for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);return res;}
int getinv(int x){return qpow(x,mod-2);}
void initinv()
{
inv[1]=1;
for(int i=2;i<N;++i) inv[i]=mod-mul(mod/i,inv[mod%i]);
}
pii mul(pii x,pii y,int val){return mkp(upm(mul(x.fi,y.fi)+mul(mul(x.se,y.se),val)),upm(mul(x.fi,y.se)+mul(x.se,y.fi)));}
int qpow(pii x,int y,int val)
{
pii res=mkp(1,0);
for(;y;y>>=1,x=mul(x,x,val))if(y&1)res=mul(res,x,val);
return res.fi;
}
int calcCipolla(int x)
{
int y=rand()%mod;
while(qpow(upm(mul(y,y)-x),(mod-1)/2)!=mod-1) y=rand()%mod;
return qpow(mkp(y,1),(mod+1)/2,upm(mul(y,y)-x));
}
}
using namespace Math;
namespace Poly
{
int m,L,rev[N];
void ntt(int *a,int n,int f)
{
for(int i=0;i<n;++i) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int i=1;i<n;i<<=1)
{
int wn=qpow(G,(mod-1)/(i<<1));
if(!~f) wn=getinv(wn);
for(int j=0;j<n;j+=i<<1)
{
int w=1;
for(int k=0;k<i;++k,w=mul(w,wn))
{
int x=a[j+k],y=mul(w,a[i+j+k]);
a[j+k]=upm(x+y);a[i+j+k]=upm(x-y);
}
}
}
if(!~f) for(int i=0,inv=getinv(n);i<n;++i) a[i]=mul(a[i],inv);
}
void reget(int n)
{
for(m=1,L=0;m<=2*n;m<<=1,++L);
for(int i=0;i<m;++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
}
void polymul(int *a,int *b,int *c)
{
ntt(a,m,1);ntt(b,m,1);
for(int i=0;i<m;++i) c[i]=mul(a[i],b[i]);
ntt(c,m,-1);
}
void polyder(int *a,int deg)
{
for(int i=0;i<deg-1;++i) a[i]=mul(a[i+1],i+1);
a[deg-1]=0;
}
void polyint(int *a,int deg)
{
for(int i=deg-1;i;--i) a[i]=mul(a[i-1],inv[i]);
a[0]=0;
}
void polyinv(int *a,int *b,int deg)//B(x) = G(x)(2-G(x)A(x))
{
if(deg==1){b[0]=getinv(a[0]);return;}
polyinv(a,b,(deg+1)>>1);
static int A[N],B[N];
reget(deg);copy(a,a+deg,A);fill(A+deg,A+m,0);copy(b,b+deg,B);fill(B+deg,B+m,0);
ntt(A,m,1);ntt(B,m,1);
for(int i=0;i<m;++i) A[i]=mul(A[i],mul(B[i],B[i]));
ntt(A,m,-1);
for(int i=0;i<deg;++i) b[i]=upm(mul(2,b[i])-A[i]);
fill(A,A+m,0);fill(B,B+m,0);
}
void polydiv(int *a,int *b,int *c,int dega,int degb)//a/b,A^r(x)=B^r(x)D^r(x),D^r(x) we need
{
static int A[N],B[N];
copy(b,b+degb,A);reverse(A,A+degb);polyinv(A,B,dega-degb+1);
copy(a,a+dega,A);reverse(A,A+dega);
reget(dega);polymul(A,B,A);
for(int i=0;i<=dega-degb;++i) c[i]=A[i];
reverse(c,c+dega-degb+1);
fill(A,A+m,0);fill(B,B+m,0);
}
void polymod(int *a,int *b,int *c,int dega,int degb)
{
static int A[N],B[N];
polydiv(a,b,A,dega,degb);copy(b,b+degb,B);
reget(dega);polymul(A,B,A);
for(int i=0;i<degb-1;++i) c[i]=upm(a[i]-A[i]);
fill(A,A+m,0);fill(B,B+m,0);
}
void polyln(int *a,int *b,int deg)
{
static int A[N],B[N];
polyinv(a,A,deg);copy(a,a+deg,B);polyder(B,deg);
reget(deg);polymul(A,B,A);
for(int i=0;i<deg;++i) b[i]=A[i];
polyint(b,deg);
fill(A,A+m,0);fill(B,B+m,0);
}
void polyexp(int *a,int *b,int deg)//newton
{
if(deg==1){b[0]=1;return;}
polyexp(a,b,(deg+1)>>1);
static int A[N],B[N];fill(A,A+deg*2,0);fill(B,B+deg*2,0);
polyln(b,B,deg);
for(int i=0;i<deg;++i) B[i]=(mod+(!i)-B[i]+a[i])%mod;
copy(b,b+deg,A);reget(deg);polymul(A,B,A);
for(int i=0;i<deg;++i) b[i]=A[i];
fill(A,A+m,0);fill(B,B+m,0);
}
void polysqrt(int *a,int *b,int deg)//(B(x)=A(x)+G^2(x))/2G(x)=A(x)/2G(x)+1/2G(x)
{
if(deg==1){b[0]=calcCipolla(a[0]);gmin(b[0],mod-b[0]);return;}
polysqrt(a,b,(deg+1)>>1);
static int A[N],B[N];
polyinv(b,B,deg);
reget(deg);copy(a,a+deg,A);fill(A+deg,A+m,0);
polymul(A,B,A);
for(int i=0;i<deg;++i) b[i]=mul(inv[2],upm(b[i]+A[i]));
fill(A,A+m,0);fill(B,B+m,0);
}
void polypow(int *a,int *b,int deg,int K)
{
static int A[N];
polyln(a,A,deg);
for(int i=0;i<deg;++i) A[i]=mul(A[i],K);
polyexp(A,b,deg);
fill(A,A+deg,0);
}
}
using namespace Poly;
namespace DreamLolita
{
int n,K;
int a[N],b[N],c[N],d[N],f[N];
void solution()
{
srand(19260817);initinv();
n=read()+1;K=read();
for(int i=0;i<n;++i) f[i]=a[i]=read();
polysqrt(a,b,n);polyinv(b,c,n);polyint(c,n);polyexp(c,d,n);
for(int i=0;i<n;++i) a[i]=((!i)*2+(bool)i*f[i]-d[i]+mod)%mod;
fill(b,b+n,0);polyln(a,b,n);b[0]=1;
fill(c,c+n,0);polypow(b,c,n,K);
polyder(c,n);
for(int i=0;i<n-1;++i) writesp(c[i]);
}
}
int main()
{
#ifdef Durant_Lee
freopen("LOJ150.in","r",stdin);
freopen("LOJ150.out","w",stdout);
#endif
DreamLolita::solution();
return 0;
}