【XSY3927】二叉树
二叉树
题意
http://xsy.gdgzez.com.cn/JudgeOnline/problem.php?id=3927
Solution
二你妈。
首先来说这个二叉树应该是一个“满二叉树”,也就是除叶子外每个结点都有2个儿子,于是对于n个叶子的“满二叉树”,结点个数必为2n-1个,这个可以通过度数来判断。
好了说正题。
我们设\(f_i\)表示有i个叶子的时候的答案。
不难发现,\(f_i=\begin{cases}1,i=1\\\sum_{j=1}^{n-1}f_jf_{i-j}c_j\end{cases}\),其中\(c_{s_i}=v_i\),其他时候为A。
那么我们给\(v_i\)全部减掉A,就可以得到如下的式子:
\[\begin{aligned} f_i = \sum_{j=1}^{n-1}Af_jf_{i-j}+\sum_{j=1}^{k}v_jf_{s_j}f_{i-s_j} \end{aligned}
\]
我们再令\(F(x)\)为\(f\)的生成函数,\(G(x)=\sum_{j=1}^{k}v_jf_{s_j}x^{s_j}\),那么容易得到:
\[F(x)=AF^2(x)+F(x)G(x)+x
\]
然后这是一个二次方程,于是有:
\[F(x)=\frac{1-G(x)-\sqrt{(1-G(x))^2-4Ax}}{2A}
\]
由于常数项为0,所以我们这里取负号。
考虑令\(P(x)=(1-G(x))^2-4Ax\),\(Q(x)=\sqrt {P(x)}\)
然后对于\(Q(x)=\sqrt {P(x)}\),我们两边求导一下:
\[\begin{aligned}
Q'(x) &= \frac{P'(x)}{2\sqrt{P(x)}}\\
\end{aligned}
\]
两边乘上\(P(x)\)得到:
\[Q'(x)P(x) = \frac{P'(x)Q(x)}{2}\\
\]
考虑第\([x^n]\)项系数,得到:
\[\sum_{i} (n-i+1)P_iQ_{n-i+1}=\frac{1}{2}\sum_{i}iP_iQ_{n-i+1}
\]
容易发现\(P_0=1\),那么有:
\[(n+1)Q_{n+1}=\sum_i (\frac{3}{2}i-n-1)P_iQ_{n-i+1}
\]
容易发现对于\(G(x)\)来说只有\(k\)项是有值的,于是\(P(x)\)最多有\(k^2\)项有值,暴力计算就可以了。
#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
const int mod=1e9+7;
const int div2=5e8+4;
const int div32=5e8+5;
int divA;
const int MAXN=1000010;
inline int add(int a,int b){return (a+b)>=mod?a+b-mod:a+b;}
inline int dec(int a,int b){return a-b<0?a-b+mod:a-b;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline int qpow(int n,int k){
int ret=1;
while(k){
if(k&1)ret=mul(ret,n);
n=mul(n,n);
k>>=1;
}
return ret;
}
int n,k,A;
int s[MAXN],v[MAXN];
int val[MAXN];
map<int,int>::iterator it;
struct poly{
vector<pii> vec;
int get(int x){
for(int i=0;i<vec.size();++i){
if(vec[i].fi==x)return vec[i].se;
}
return 0;
}
void ins(int x,int y){
for(int i=0;i<vec.size();++i){
if(vec[i].fi==x){
vec[i].se=add(vec[i].se,y);
return;
}
}
vec.push_back(mp(x,y));
}
void upd(int x,int y){
for(int i=0;i<vec.size();++i){
if(vec[i].fi==x){
vec[i].se=y;
return;
}
}
vec.push_back(mp(x,y));
}
poly sqr(){
poly now;
map<int,int> tmp;
now.vec.clear();
for(int i=0;i<vec.size();++i){
for(int j=0;j<vec.size();++j){
tmp[vec[i].fi+vec[j].fi]=add(tmp[vec[i].fi+vec[j].fi],mul(vec[i].se,vec[j].se));
}
}
for(it=tmp.begin();it!=tmp.end();++it){
int x=(*it).fi,y=(*it).se;
now.ins(x,y);
}
return now;
}
void check(){
for(int i=0;i<vec.size();++i){
printf("%d %d\n",vec[i].fi,vec[i].se);
}
}
}G,P;
int F[1000010];
int Q[1000010];
int main(){
memset(val,-1,sizeof(val));
scanf("%d%d%d",&n,&k,&A);
for(int i=1;i<=k;++i){
scanf("%d%d",&s[i],&v[i]);
if(v[i]-A)val[s[i]]=dec(v[i],A);
}
divA=qpow(add(A,A),mod-2);
F[1]=1;
G.ins(0,1);if(val[1]!=-1)G.ins(1,mod-val[1]);
P=G.sqr();P.ins(1,mod-mul(4,A));
Q[0]=1;Q[1]=mul(P.get(1),div2);
for(int i=2;i<=n;++i){
for(int j=0;j<P.vec.size();++j){
pii now=P.vec[j];
if(now.fi==0||now.fi>i)continue;
Q[i]=add(Q[i],mul(mul(now.se,Q[i-now.fi]),dec(mul(div32,now.fi),i)));
}
Q[i]=mul(Q[i],qpow(i,mod-2));
F[i]=mul(dec(G.get(i),Q[i]),divA);
if(val[i]!=-1){
G.upd(i,mod-mul(val[i],F[i]));
P=G.sqr();
P.ins(1,mul(mod-4,A));
Q[i]=dec(Q[i],mul(F[i],val[i]));
}
}
printf("%d\n",F[n]);
}