【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;
}
posted @ 2018-05-23 21:34  LesRoad  阅读(424)  评论(0编辑  收藏  举报