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;
}
时间: 2024-11-05 12:28:20