BZOJ3625: [Codeforces Round #250]小朋友和二叉樹(OGF+牛頓迭代)
阿新 • • 發佈:2018-12-24
題解:
看到這種二叉樹的題第一反應就是類似卡特蘭數的遞推。或者另外一種直觀的想法是看成一個點和兩邊的二叉樹的拼接,注意這裡不帶標號。
那麼很簡單了,對於點和二叉樹分別構造
解二次方程:
捨去減的根,因為它在0處不收斂。
然後直接牛頓迭代即可,具體可以參考這裡
#include <bits/stdc++.h>
typedef long long LL;
using namespace std;
inline int rd() {
char ch=getchar(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=getchar();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}
return i*f;
}
inline void W(int x){
static int buf[50];
if(!x) {putchar('0'); return;}
if(x<0) {putchar('-'); x=-x;}
while (x) {buf[++buf[0]]=x%10; x/=10;}
while(buf[0]) putchar(buf[buf[0]--]+'0');
}
const int N=1e5+50;
const int Mod=998244353;
const int G=3;
const int inv2=499122177;
inline int power(int a,int b) {
int rs=1;
for(;b;b>>=1,a=(LL)a*a%Mod) if(b&1) rs=(LL)rs*a%Mod;
return rs;
}
int n,m,k,bb[N*8 ],f[N*8],g[N*8],ig[N*8],tp[N*8],tp2[N*8],w[N*8],pos[N*8];
inline void dft(int *a) {
for(int i=1;i<k;i++) pos[i]=(i&1) ?((pos[i>>1]>>1)^(k>>1)) :(pos[i>>1]>>1);
for(int i=1;i<k;i++) if(pos[i]>i) swap(a[pos[i]],a[i]);
for(int bl=1;bl<k;bl<<=1) {
int tl=bl<<1,wn=power(G,(Mod-1)/tl); w[0]=1;
for(int i=1;i<bl;i++) w[i]=(LL)w[i-1]*wn%Mod;
for(int bg=0;bg<k;bg+=tl)
for(int j=0;j<bl;j++) {
int &t1=a[bg+j],&t2=a[bg+j+bl],t3=(LL)t2*w[j]%Mod;
t2=(t1-t3<0?t1-t3+Mod:t1-t3);
t1=(t1+t3>=Mod?t1+t3-Mod:t1+t3);
}
}
}
inline void calc_inverse(int *a,int *b,int len) {
if(len==1) {b[0]=power(a[0],Mod-2); return;}
if(len!=1) calc_inverse(a,b,len>>1);
k=len<<1;
for(int i=0;i<len;i++) tp[i]=b[i];
for(int i=(len>>1);i<len;i++) tp[i]=0;
for(int i=0;i<len;i++) tp2[i]=a[i];
for(int i=len;i<k;i++) tp[i]=(tp2[i]=0);
dft(tp); dft(tp2);
for(int i=0;i<k;i++) tp[i]=(2ll*tp[i]%Mod - (LL)tp2[i]*tp[i]%Mod*tp[i]%Mod +Mod)%Mod;
dft(tp); reverse(tp+1,tp+k);
const int inv=power(k,Mod-2);
for(int i=0;i<len;i++) b[i]=(LL)tp[i]*inv%Mod;
for(int i=len;i<k;i++) b[i]=0;
}
inline void calc_root(int *a,int *b,int len) {
if(len==1) {b[0]=sqrt(a[0]); return;}
if(len!=1) calc_root(a,b,len>>1);
k=len<<1;
for(int i=0;i<len;i++) b[i]=b[i]*2%Mod;
calc_inverse(b,ig,len);
for(int i=0;i<len;i++) tp[i]=a[i];
for(int i=0;i<len;i++) tp2[i]=ig[i];
for(int i=len;i<k;i++) (tp[i]=(tp2[i]=0));
dft(tp); dft(tp2);
for(int i=0;i<k;i++) tp[i]=(LL)tp[i]*tp2[i]%Mod;
dft(tp); reverse(tp+1,tp+k);
const int inv=power(k,Mod-2);
for(int i=0;i<k;i++) tp[i]=(LL)tp[i]*inv%Mod;
for(int i=0;i<len;i++) b[i]=(tp[i]+(LL)b[i]*inv2%Mod*inv2%Mod)%Mod;
for(int i=len;i<k;i++) b[i]=0;
}
int main() {
n=rd(),m=rd(); bb[0]=1;
for(int i=1;i<=n;i++) bb[rd()]=Mod-4;
int len; for(len=1;len<=m;len<<=1);
calc_root(bb,f,len); f[0]++;
calc_inverse(f,g,len);
for(int i=1;i<=m;i++) g[i]=g[i]*2%Mod;
for(int i=1;i<=m;i++) W(g[i]),putchar('\n');
}