二叉树
题意
http://xsy.gdgzez.com.cn/JudgeOnline/problem.php?id=3927
Solution
二你妈。
首先来说这个二叉树应该是一个“满二叉树”,也就是除叶子外每个结点都有2个儿子,于是对于n个叶子的“满二叉树”,结点个数必为2n-1个,这个可以通过度数来判断。
好了说正题。
我们设(f_i)表示有i个叶子的时候的答案。
不难发现,(f_i=egin{cases}1,i=1\sum_{j=1}^{n-1}f_jf_{i-j}c_jend{cases}),其中(c_{s_i}=v_i),其他时候为A。
那么我们给(v_i)全部减掉A,就可以得到如下的式子:
[egin{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)}),我们两边求导一下:
[egin{aligned}
Q'(x) &= frac{P'(x)}{2sqrt{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
",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
",F[n]);
}