描述
题解
拿到这道题,很容易发现,有效的数据只有n
,其他的连通都是烟雾弹,毕竟保证是一颗树。
想到这里,知道是需要找规律推公式,可是半天没能推出公式,然后参考了一些大神的思路……
因为每炸毁一条边就多出一个连通图,所以最优是一个连通,最差是n
个连通。选择一条边的概率是1/2
,选择n
条边就是1/2^(n-1)
,那么最后题目要求乘以2^(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]+2^(i-2),ans[1]=1
代码
#include <iostream>
using namespace std;
typedef long long ll;
const int _MOD = 1e9 + 7;
const int MAXN = 1e5 + 5;
/*
* deBug
ll c[50][50];
void init()
{
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];
//快速求幂
ll power(ll a, ll b)
{
ll ans = 1;
while (b)
{
if (b & 1)
{
ans = (ans * a) % _MOD;
b--;
}
b >>= 1;
a = (a * a) % _MOD;
}
return ans;
}
void init()
{
ans[1] = 1;
for (int i = 2; i < MAXN; i++)
{
ans[i] = 2 * ans[i - 1] + power(2, i - 2);
ans[i] %= _MOD;
}
}
int main(int argc, const char * argv[])
{
init();
int n, x, y;
while (cin >> n)
{
for (int i = 0; i < n - 1; i++)
{
cin >> x >> y;
}
cout << ans[n] << '\n';
}
return 0;
}