【XSY3927】二叉树

二叉树

题意

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]);
}
原文地址:https://www.cnblogs.com/youddjxd/p/14919714.html