码迷,mamicode.com
首页 > 编程语言 > 详细

51NOD 1632 B君的连通(推公式)——算法马拉松16

时间:2016-08-01 10:47:04      阅读:199      评论:0      收藏:0      [点我收藏+]

标签:

传送门
B国拥有n个城市,其交通系统呈树状结构,即任意两个城市存在且仅存在一条交通线将其连接。A国是B国的敌国企图秘密发射导弹打击B国的交通线,现假设每条交通线都有50%的概率被炸毁,B国希望知道在被炸毁之后,剩下联通块的个数的期望是多少?

Input
一个数n(2<=n<=100000)
接下来n-1行,每行两个数x,y表示一条交通线。(1<=x,y<=n)
数据保证其交通系统构成一棵树。
Output
一行一个数,表示答案乘2^(n-1)后对1,000,000,007取模后的值。
Input示例
3
1 2
1 3
Output示例
8
解题思路:
就是推一下公式,然后打一个表找一下规律就行了,因为每炸毁一条边就多一个连通图,所以就根据这个推出公式,因为选一条边的概率是 12:然后进行操作的概率就是 12n?1),然后再乘以 2n?1 就抵消了,所以公式就是:
1+2?C(n?1,1)+3?C(n?1,2)+...+n?C(n?1,n?1)
然后打个表发现上述式子可以简化为:
ans[i]=2?ans[i?1]+2i?2,ans[1]=1
My Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
typedef long long LL;
const LL MOD = 1e9+7;
const int MAXN = 100000+5;
LL quick_MOD(LL a, LL b)
{
    LL ans = 1;
    while(b)
    {
        if(b & 1)
            ans = (ans*a)%MOD;
        b>>=1;
        a = (a*a)%MOD;
    }
    return ans;
}

LL c[50][50];
void Init1()
{
    for(int i=0; i<50; i++)
        c[i][0] = 1;
    for(int i=1; i<50; i++)
    {
        for(int j=1; j<=i; j++)
        {
            c[i][j] = c[i-1][j]+c[i-1][j-1];
        }
    }
    for(int i=1; i<=20; i++)
    {
        LL sum = 0;
        for(int j=0; j<=i; j++)
        {
            sum += (j+1)*c[i-1][j];
        }
        cout<<"i = "<<i<<" : "<<sum<<endl;
    }
}
LL ans[MAXN];
void Init()
{
    ans[1] = 1;
    for(int i=2; i<MAXN; i++)
    {
        ans[i] = 2*ans[i-1]+quick_MOD(2,i-2);
        ans[i] %= MOD;
    }
}
int main()
{
    ///Init1();
    Init();
    LL n, x, y;
    while(cin>>n)
    {
        for(int i=0; i<n-1; i++)
            cin>>x>>y;
        cout<<ans[n]<<endl;
    }
    return 0;
}

51NOD 1632 B君的连通(推公式)——算法马拉松16

标签:

原文地址:http://blog.csdn.net/qingshui23/article/details/52083491

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!