【zznu-2093】毁掉这颗二叉树
题目描述
广寒宫下有株二叉树,树上共有n个节点,通过n-1条树枝连接,树下有一只玉兔,吴刚提着斧子站在一旁。
他恼恨一切同他争夺嫦娥的事物,所以他决定通过砍二叉树上的n-1条树枝来毁掉这颗二叉树。
妙的是,这些树枝只能被砍一次,而且被砍后有一半的概率立即长出。
吴刚砍了n斧子后罢手了,他打算“不眠倚桂树”。你来猜猜,现在这株二叉树有多少联通块?(即联通块的期望值)
已知:最后一斧子砍了玉兔。
输入
输入一个正整数T(1<=T<=50)
接下来T行,每行输入一个正整数n,代表二叉树的节点数,2<=n<=1e5。
输出
输出联通块的期望值,答案的数据可能很大,所以输出答案乘2^(n-1)后再对1e9+7取模
样例输入
1
2
样例输出
3
就是让求 1*C(n-1, 0) + 2*C(n-1, 1) + 3*C(n-1, 2) + ... + n*C(n-1, n-1) 的值
除法取余利用逆元求解,逆元可以用inv[i]=(mod-mod/i)*inv[mod%i]%mod线性求出。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
typedef long long LL;
const LL mod = 1e9+7;
int inv[N];
int main()
{
int t, n;
inv[1] = 1;
for(int i = 2; i <= 1e5; i++)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
cin>>t;
while(t--)
{
scanf("%d", &n);
LL ans = 1, temp = 1;
for(int i = 2; i <= n; i++)
{
temp = temp*(n-i+1)%mod*inv[i-1]%mod;
ans = (ans + i*temp) % mod;
}
printf("%lld\n", ans);
}
return 0;
}