【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]);
}
posted @ 2021-06-22 17:59  FakeDragon  阅读(78)  评论(0编辑  收藏  举报