[Codeforces438E]The Child and Binary Tree(多項式開根+多項式求逆)
阿新 • • 發佈:2018-12-24
=== ===
這裡放傳送門
=== ===
題解
這道題的意思是給定一個集合,求有多少形態不同的二叉樹滿足每個點的權值都屬於這個集合並且總點權等於i。
設
然而這樣算出來的這一坨東西就等於 (x)=F2(x)×C(x)+1
這是一個生成函式的一元二次方程,把它解出來得到
然而這好像並不是一個有多解的問題,於是觀察解出來的這兩個多項式。
誒這樣一看好像兩個並沒有什麼區別啊都挺可以的啊???
那分子分母上都有C(x)看起來不是很友好,我們把上下同時乘以
這樣子看起來就比較好辦了,因為當x趨近於0的時候C(x)也趨近於0,如果下面取的是 √
然後多項式開根和多項式求逆。。。。
多項式怎麼開根????
ATP懶得寫了丟連結跑[戳這裡]
程式碼
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int Mod=998244353;
const int G=3;
const int inv2=499122177;
int n,m,R[300010],N,M,inv[300010],rt[300010],v[300010],c[300010],tmp[300010];
int powww(int a,int t){
int ans=1;a%=Mod;
while (t!=0){
if (t&1) ans=((long long)ans*(long long)a)%Mod;
a=((long long)a*(long long)a)%Mod;t>>=1;
}
return ans;
}
void NTT(int N,int *a,int opt){
int w,wn,x,y;
for (int i=1;i<=N;i++)
if (i<R[i]) swap(a[i],a[R[i]]);
for (int k=1;k<N;k<<=1){
wn=powww(G,(Mod-1)/(k<<1));
for (int i=0,p=(k<<1);i<N;i+=p){
w=1;
for (int j=0;j<k;j++){
x=a[i+j];y=(long long)w*(long long)a[i+j+k]%Mod;
a[i+j]=(x+y)%Mod;
a[i+j+k]=(x-y)%Mod;
w=(long long)w*(long long)wn%Mod;
}
}
}
if (opt==-1) reverse(a+1,a+N);
}
void Inverse(int N,int *a,int *b){
if (N==1){b[0]=powww(a[0],Mod-2);return;}
int K=(N<<1),L=0;
long long inv=powww(K,Mod-2);
Inverse(N>>1,a,b);
for (int i=0;i<N;i++) tmp[i]=a[i];
for (int i=N;i<=K;i++) tmp[i]=0;
for (int i=1;i<K;i<<=1) L++;
for (int i=0;i<=K;i++)
R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
NTT(K,tmp,1);NTT(K,b,1);
for (int i=0;i<K;i++)
tmp[i]=(long long)b[i]*(long long)(2-(long long)b[i]*(long long)tmp[i]%Mod)%Mod;
NTT(K,tmp,-1);
for (int i=0;i<N;i++) b[i]=(long long)tmp[i]*(long long)inv%Mod;
for (int i=N;i<=K;i++) b[i]=0;
}
void SqRoot(int N,int *a,int *b){
if (N==1){b[0]=1;return;}
int L=0,K=N<<1;
int inv=powww(K,Mod-2);
SqRoot(N>>1,a,b);
for (int i=0;i<=N;i++) v[i]=0;
Inverse(N,b,v);
for (int i=0;i<N;i++) tmp[i]=a[i];
for (int i=N;i<=K;i++) tmp[i]=0;
for (int i=1;i<K;i<<=1) L++;
for (int i=0;i<=K;i++)
R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
NTT(K,tmp,1);NTT(K,v,1);NTT(K,b,1);
for (int i=0;i<K;i++)
tmp[i]=(long long)inv2*(long long)(b[i]+(long long)v[i]*(long long)tmp[i]%Mod)%Mod;
NTT(K,tmp,-1);
for (int i=0;i<N;i++) b[i]=(long long)tmp[i]*(long long)inv%Mod;
for (int i=N;i<=K;i++) b[i]=0;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
int x;scanf("%d",&x);
c[x]=-4;
}
c[0]=1;
for (N=1;N<=m;N<<=1);
SqRoot(N,c,rt);
rt[0]++;Inverse(N,rt,inv);
for (int i=1;i<=m;i++)
inv[i]=(inv[i]*2%Mod+Mod)%Mod;
for (int i=1;i<=m;i++) printf("%d\n",inv[i]);
return 0;
}