【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; }