[CF438E] 小朋友和二叉树
多项式开根的板子题
因为忘了又去推了一次开根
每一个值的计算都要枚举左子树放多少,中间的点放多少,右子树放多少
不难看出式三个多项式卷积的形式,特殊的是\(f(0)=1\)
\[f(x)=a(x)*f^2(x)+1
\]
解得
\[f(x)=\frac{1\plusmn\sqrt{1-4a(x)}}{2a}
\]
带个0舍掉一个解
\[f(x)=\frac{1-\sqrt{1-4a(x)}}{2a}
\]
敲完之后发现输出的都是0,原因是这个分母常数项是0,不能求逆
我们进行分母无理化的迷惑操作
\[\frac{(1-\sqrt{1-4a(x)})(1+\sqrt{1+4a(x)})}{2a(1+\sqrt{1+4a(x)})}
\]
\[\frac{4a}{2a(1+\sqrt{1+4a(x)})}
\]
\[\frac{2}{1+\sqrt{1+4a(x)}}
\]
然后就可以做了
#include<cstdio>
#include<algorithm>
using namespace std;
namespace Patchouli{
const int N=414514;
const int MOD=998244353;
const int G=3;
const int INV=332748118;
const int INV2=499122177;
long long tmp[N],res[N];
long long f[N],g[N],ans[N];
int limit,len,reverse[N];
inline long long pow(long long x,int y){
long long ans=1;
while(y){
if(y&1)ans=ans*x%MOD;
x=x*x%MOD;
y>>=1;
}
return ans;
}
inline void NTT(long long *f,int res){
long long tx,ty,t,w;
for(int i=0;i<limit;++i)
if(i<reverse[i])
swap(f[i],f[reverse[i]]);
for(int i=1;i<limit;i<<=1){
t=pow(res,(MOD-1)/(i<<1));
for(int j=0;j<limit;j+=(i<<1)){
w=1;
for(int k=0;k<i;++k,w=w*t%MOD){
tx=f[j+k],ty=f[j+i+k]*w%MOD;
f[j+k]=(tx+ty)%MOD;
f[j+i+k]=(tx-ty)%MOD;
}
}
}
if(res==INV){
long long inv=pow(limit,MOD-2);
for(int i=0;i<limit;++i)
f[i]=f[i]*inv%MOD;
}
}
void inv(int n,long long *f,long long *g){
if(n==1){
g[0]=pow(f[0],MOD-2);
return;
}
inv((n+1)>>1,f,g);
limit=1,len=0;
while(limit<(n<<1))
limit<<=1,++len;
for(int i=0;i<limit;++i)
reverse[i]=(reverse[i>>1]>>1)|((i&1)<<(len-1));
for(int i=0;i<n;++i)
tmp[i]=f[i];
for(int i=n;i<limit;++i)
tmp[i]=0;
NTT(tmp,G),NTT(g,G);
for(int i=0;i<limit;++i)
g[i]=(2-g[i]*tmp[i]%MOD)*g[i]%MOD;
NTT(g,INV);
for(int i=n;i<limit;++i)
g[i]=0;
}
void sqrt(int n,long long *f,long long *g){
if(n==1){
g[0]=1;
return;
}
sqrt((n+1)>>1,f,g);
inv(n,g,res);
limit=1,len=0;
for(int i=0;i<limit;++i)
reverse[i]=(reverse[i>>1]>>1)|((i&1)<<(len-1));
while(limit<(n<<1))
limit<<=1,++len;
for(int i=0;i<n;++i)
tmp[i]=f[i];
for(int i=n;i<limit;++i)
tmp[i]=0;
NTT(g,G),NTT(tmp,G),NTT(res,G);
for(int i=0;i<limit;++i)
g[i]=(g[i]-(g[i]*g[i]-tmp[i])%MOD*INV2%MOD*res[i])%MOD;
NTT(g,INV);
for(int i=0;i<limit;++i)
res[i]=0;
for(int i=n;i<limit;++i)
g[i]=0;
}
inline int read(){
int a=1,b=0;char t;
do{t=getchar();if(t=='-')a=-1;}while(t>'9'||t<'0');
do{b=b*10-'0'+t;t=getchar();}while(t>='0'&&t<='9');
return a*b;
}
int QAQ(){
int n=read(),m=read()+1;
for(int i=1;i<=n;++i)
f[read()]=-4;
f[0]+=1;
sqrt(m,f,g);
g[0]=1+g[0]%MOD;
inv(m,g,ans);
for(int i=1;i<m;++i)
printf("%lld\n",(ans[i]*2%MOD+MOD)%MOD);
return false;
}
}
int main(){
return Patchouli::QAQ();
}