传送门
PROBLEM
SOL
F的常数项为1,G的常数项为0,带入方程,舍去减的根。(说是因为不收敛?)
多项式开根+求逆
(code附赠两种开根写法)
CODE
#include<bits/stdc++.h>
#define pf printf
#define sf scanf
#define cs const
#define ll long long
#define db double
using namespace std;
#define in red()
inline int red()
{
int data=0;int w=1; char ch=0;
ch=getchar();
while(ch!='-' && (ch<'0' || ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0' && ch<='9') data=(data<<3)+(data<<1)+ch-'0',ch=getchar();
return data*w;
}
cs int N=1e5+10,mod=998244353;
inline int mul(cs int &a,cs int &b){return 1ll*a*b%mod;}
inline int add(cs int &a,cs int &b){return a+b>mod? a-mod+b:a+b;}
inline int dec(cs int &a,cs int &b){return a-b<0? a+mod-b:a-b;}
inline int ksm(int a,int b){int ans=1;for(;b;b>>=1,a=mul(a,a))if(b&1)ans=mul(ans,a);return ans;}
#define ri register int
typedef vector<int> node;
int lim,tim,w[30],inv[30],inv2,n,m;
node rev[30];
inline void init_w(){
w[22]=ksm(3,(mod-1)>>23);inv[0]=1;
for(ri i=21;~i;--i)w[i]=mul(w[i+1],w[i+1]);
for(ri i=1,mt=ksm(2,mod-2);i<=22;++i)inv[i]=mul(inv[i-1],mt);
}
inline void init(cs int &up){
lim=1;tim=0;
while(lim<up)lim<<=1,++tim;
if(rev[tim].size())return;
rev[tim].resize(lim);
for(ri i=0;i<lim;++i)rev[tim][i]=(rev[tim][i>>1]>>1)|((i&1)*(lim>>1));
}
inline void ntt(node &f,bool kd){
for(ri i=0;i<lim;++i)if(rev[tim][i]<i)swap(f[i],f[rev[tim][i]]);
for(ri mid=1,t=0;mid<lim;mid<<=1,++t){
for(ri i=0,d=mid<<1;i<lim;i+=d){
for(ri j=0,now=1,p0,p1;j<mid;++j,now=mul(now,w[t])){
p0=f[i+j],p1=mul(now,f[i+j+mid]);
f[i+j]=add(p0,p1);f[i+j+mid]=dec(p0,p1);
}
}
}
if(kd)return;
reverse(++f.begin(),f.end());
for(ri i=0;i<lim;++i)f[i]=mul(f[i],inv[tim]);
}
inline node operator *(node a,node b){
int n=a.size(),m=b.size(),tot=n+m-1;
if(tot<=168){
node c(tot);
for(ri i=0;i<n;++i)
for(ri j=0;j<m;++j)
c[i+j]=add(c[i+j],mul(a[i],b[j]));
return c;
}
init(tot);
a.resize(lim);ntt(a,1);
b.resize(lim);ntt(b,1);
for(ri i=0;i<lim;++i)a[i]=mul(a[i],b[i]);
return ntt(a,0),a.resize(tot),a;
}
inline node node_inv(node &a,int k){
node c,b(1,ksm(a[0],mod-2));
for(ri lim=4,up=k<<2;lim<up;lim<<=1){
init(lim);
c=a;c.resize(lim>>1);
c.resize(lim);ntt(c,1);
b.resize(lim);ntt(b,1);
for(ri i=0;i<lim;++i)b[i]=mul(b[i],dec(2,mul(c[i],b[i])));
ntt(b,0);b.resize(lim>>1);
}
return b.resize(k),b;
}
inline node node_sqrt(node &a,int k){
node c,b(1,1),d;
for(ri lim=4,up=k<<2;lim<up;lim<<=1){
d=node_inv(b,lim>>1);
init(lim);
c=a;c.resize(lim>>1);
c.resize(lim);ntt(c,1);
d.resize(lim);ntt(d,1);
for(ri i=0;i<lim;++i)d[i]=mul(d[i],c[i]);
ntt(d,0);b.resize(lim>>1);
for(ri i=0,up=(lim>>1);i<up;++i)b[i]=add(b[i],d[i]),b[i]=mul(b[i],inv2);
}
return b.resize(k),b;
}
//inline node node_sqrt(node a,int n){
// node b(1,1),c,d;
// for(int lim=4;lim<(n<<2);lim<<=1){
// c=a;c.resize(lim>>1);
// init(lim);d=node_inv(b,lim>>1);
// c.resize(lim);ntt(c,1);
// d.re size(lim);ntt(d,1);
// for(int i=0;i<lim;i++) c[i]=mul(c[i],d[i]);
// ntt(c,0);b.resize(lim>>1);
// for(int i=0;i<(lim>>1);i++) b[i]=mul(inv2,add(b[i],c[i]));
// }
// b.resize(n);return b;
//}
node a;
signed main (){
init_w();
inv2=ksm(2,mod-2);
n=in,m=in;
a.resize(N-3);
for(ri i=1;i<=n;++i)++a[in];
a.resize(m+1);
for(ri i=0;i<=m;++i)a[i]=mul(-4,a[i]);
a[0]=add(1,a[0]);
a=node_sqrt(a,m+1);
a[0]=add(1,a[0]);
a=node_inv(a,m+1);
for(ri i=1;i<=m;++i)pf("%d\n",mul(2,a[i]));
return 0;
}