您的位置:首页 > 其它

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

2016-08-01 10:27 330 查看
传送门

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\frac{1}2:然后进行操作的概率就是 12n−1)\frac{1}{2^{n-1})},然后再乘以 2n−12^{n-1} 就抵消了,所以公式就是:

1+2∗C(n−1,1)+3∗C(n−1,2)+...+n∗C(n−1,n−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]=1ans[i] = 2*ans[i-1]+2^{i-2}, ans[1] = 1

MyMy CodeCode:

#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
<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: