生活随笔
收集整理的這篇文章主要介紹了
CF438E:The Child and Binary Tree(生成函数)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
解析:
設計 fif_ifi? 表示權值為 iii 的方案數,f0=1f_0=1f0?=1。
枚舉根節點權值,可以寫出轉移:
fn=∑gk∑ififn?k?i=∑i+j+k=nfifjgkf_n=\sum g_k\sum_{i}f_if_{n-k-i}=\sum_{i+j+k=n}f_if_jg_kfn?=∑gk?i∑?fi?fn?k?i?=i+j+k=n∑?fi?fj?gk?
其中 gk=1g_k=1gk?=1 表示集合中有元素 kkk,gk=1g_k=1gk?=1 表示沒有元素 kkk。
設它們的生成函數為 FFF 和 GGG,就有:
F=GF2+1F=GF^2+1F=GF2+1
由于 GGG 的零次項為 000,無法求逆,考慮配方移項:
G2F2?GF+G=0G^2F^2-GF+G=0G2F2?GF+G=0
(GF?12)2=14?G(GF-\frac{1}{2})^2=\frac{1}{4}-G(GF?21?)2=41??G
GF=±14?G+12GF=±\sqrt{\frac{1}{4}-G}+\frac{1}{2}GF=±41??G?+21?
注意到,GFGFGF 的零次項應該為 000,而當右邊取正號時,零次項為 111,所以應該取負。
GF=?14?G+12=2G1+1?4GGF=-\sqrt{\frac{1}{4}-G}+\frac{1}{2}=\frac{2G}{1+\sqrt{1-4G}}GF=?41??G?+21?=1+1?4G?2G?
沒有逆,不能除下去,那我們就移過來:
G(F?(2G1+1?4G))=0G(F-(\frac{2G}{1+\sqrt{1-4G}}))=0G(F?(1+1?4G?2G?))=0
由于 GGG 系數不全為0,所以就有:
F=2G1+1?4GF=\frac{2G}{1+\sqrt{1-4G}}F=1+1?4G?2G?
上多項式開根和求逆即可。
#include<bits/stdc++.h>
using namespace std
;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
inline ll
read() {ll
x(0),f(1);char c
=getchar();while(!isdigit(c
)) {if(c
=='-')f
=-1;c
=getchar();}while(isdigit(c
)) {x
=(x
<<1)+(x
<<3)+c
-'0';c
=getchar();}return x
*f
;
}
const int N
=4e5+100;
const int mod
=998244353;
int n
,m
,k
;
inline ll
ksm(ll x
,ll k
){ll res
=1;while(k
){if(k
&1) res
=res
*x
%mod
;x
=x
*x
%mod
;k
>>=1;}return res
;
}
int niv2
=ksm(2,mod
-2);
int r
[N
];
void init(int n
,int &lim
){lim
=1;int L
=0;while(lim
<n
) lim
<<=1,L
++;for(int i
=1;i
<lim
;i
++) r
[i
]=(r
[i
>>1]>>1)|((i
&1)<<(L
-1));
}
void NTT(ll
*x
,int lim
,int op
){for(int i
=0;i
<lim
;i
++) if(i
<r
[i
]) swap(x
[i
],x
[r
[i
]]);for(int l
=1;l
<lim
;l
<<=1){ll w
=ksm(3,(mod
-1)/(l
<<1));if(op
==-1) w
=ksm(w
,mod
-2);for(int st
=0;st
<lim
;st
+=(l
<<1)){for(ll i
=0,now
=1;i
<l
;i
++,now
=now
*w
%mod
){ll u
=x
[st
+i
],v
=now
*x
[st
+i
+l
]%mod
;x
[st
+i
]=u
+v
>=mod
?u
+v
-mod
:u
+v
;x
[st
+i
+l
]=u
-v
<0?u
-v
+mod
:u
-v
;}}}if(op
==-1){ll ni
=ksm(lim
,mod
-2);for(int i
=0;i
<lim
;i
++) x
[i
]=x
[i
]*ni
%mod
;}return;
}
void copy(ll
*a
,ll
*b
,int n
,int lim
){assert(n
<=lim
);memcpy(a
,b
,sizeof(ll
)*n
);fill(a
+n
,a
+lim
,0);return;
}
void mul(ll
*a
,ll
*b
,ll
*c
,int n
,int m
){static ll u
[N
],v
[N
];static int lim
;init(n
+m
-1,lim
);copy(u
,a
,n
,lim
);copy(v
,b
,m
,lim
);NTT(u
,lim
,1);NTT(v
,lim
,1);for(int i
=0;i
<lim
;i
++) c
[i
]=u
[i
]*v
[i
]%mod
;NTT(c
,lim
,-1);return;
}
void inv(ll
*h
,ll
*f
,int n
){static ll t1
[N
],t2
[N
];static int lim
;if(n
==1){f
[0]=ksm(h
[0],mod
-2);return;}inv(h
,f
,(n
+1)>>1);init(n
<<1,lim
);fill(f
+((n
+1)>>1),f
+lim
,0);copy(t1
,f
,n
,lim
);copy(t2
,h
,n
,lim
);NTT(t1
,lim
,1);NTT(t2
,lim
,1);for(int i
=0;i
<lim
;i
++) t1
[i
]=(2*t1
[i
]-t1
[i
]*t1
[i
]%mod
*t2
[i
]%mod
+mod
)%mod
;NTT(t1
,lim
,-1);memcpy(f
,t1
,sizeof(ll
)*n
);return;
}
void Sqrt(ll
*h
,ll
*f
,int n
){static ll t1
[N
],t2
[N
];static int lim
;if(n
==1){f
[0]=1;return;}Sqrt(h
,f
,(n
+1)>>1);init(n
<<1,lim
);fill(f
+((n
+1)>>1),f
+lim
,0);inv(f
,t1
,n
);fill(t1
+n
,t1
+lim
,0);mul(h
,t1
,t1
,n
,n
);copy(t2
,f
,n
,lim
);NTT(t1
,lim
,1);NTT(t2
,lim
,1);for(int i
=0;i
<lim
;i
++) t1
[i
]=(t1
[i
]+t2
[i
])*niv2
%mod
;NTT(t1
,lim
,-1);memcpy(f
,t1
,sizeof(ll
)*n
);return;
}
void dao(ll
*h
,ll
*f
,int n
){static ll t
[N
];static int lim
;init(n
<<1,lim
);copy(t
,h
,n
,lim
);f
[n
-1]=0;for(int i
=0;i
<n
-1;i
++) f
[i
]=t
[i
+1]*(i
+1)%mod
;fill(f
+n
,f
+lim
,0);return;
}
void jifen(ll
*h
,ll
*f
,int n
){static ll t
[N
];static int lim
;init(n
<<1,lim
);copy(t
,h
,n
,lim
);f
[0]=0;for(int i
=1;i
<n
;i
++) f
[i
]=h
[i
-1]*ksm(i
,mod
-2)%mod
;fill(f
+n
,f
+lim
,0);
}
void Ln(ll
*h
,ll
*f
,int n
){static ll t1
[N
],t2
[N
];static int lim
;init(n
<<1,lim
);inv(h
,t1
,n
);fill(t1
+n
,t1
+lim
,0);dao(h
,t2
,n
);mul(t1
,t2
,t1
,n
,n
);jifen(t1
,f
,n
);return;
}
void Exp(ll
*h
,ll
*f
,int n
){static ll t1
[N
],t2
[N
],t3
[N
];static int lim
;if(n
==1){f
[0]=1;return;}Exp(h
,f
,(n
+1)>>1);init(n
<<1,lim
);fill(f
+((n
+1)>>1),f
+lim
,0);copy(t1
,f
,n
,lim
);copy(t2
,h
,n
,lim
);Ln(f
,t3
,n
);fill(t3
+n
,t3
+lim
,0);NTT(t1
,lim
,1);NTT(t2
,lim
,1);NTT(t3
,lim
,1);for(int i
=0;i
<lim
;i
++) t1
[i
]=t1
[i
]*(1+t2
[i
]-t3
[i
]+mod
)%mod
;NTT(t1
,lim
,-1);memcpy(f
,t1
,sizeof(ll
)*n
);return;
}
void solve(ll
*h
,ll
*w
,ll
*f
,int l
,int r
){static ll t1
[N
],t2
[N
];static int lim
;if(l
==r
) return;int mid
=(l
+r
)>>1;solve(h
,w
,f
,l
,mid
);int n
=(r
-l
+1),m
=(mid
-l
+1);init(n
<<1,lim
);copy(t1
,h
,n
,lim
);copy(t2
,f
+l
,m
,lim
);mul(t1
,t2
,t1
,n
,m
);for(int i
=1;i
<=m
;i
++) (w
[mid
+i
]+=2*t1
[i
])%=mod
;copy(t1
,w
,n
,lim
);copy(t2
,f
+l
,m
,lim
);mul(t1
,t2
,t1
,n
,m
);for(int i
=1;i
<=m
;i
++) (f
[mid
+i
]+=2*t1
[i
])%=mod
;solve(h
,w
,f
,mid
+1,r
);return;
}
ll a
[N
],b
[N
],c
[N
];
signed main() {
#ifndef ONLINE_JUDGE
#endifn
=read();m
=read();for(int i
=1;i
<=n
;i
++) a
[read()]=1; n
=m
+1;int lim
;init(n
<<1,lim
);for(int i
=0;i
<n
;i
++) a
[i
]=(mod
-4*a
[i
])%mod
;a
[0]=(a
[0]+1)%mod
;Sqrt(a
,b
,n
);b
[0]=(b
[0]+1)%mod
;inv(b
,c
,n
);for(int i
=0;i
<n
;i
++) c
[i
]=(c
[i
]<<1)%mod
;for(int i
=1;i
<=m
;i
++) printf("%lld\n",c
[i
]);return 0;
}
總結
以上是生活随笔為你收集整理的CF438E:The Child and Binary Tree(生成函数)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。