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

传送门

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

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

1632 B君的连通

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取模后的值. In

ASC(22)H(大数+推公式)

High Speed Trains Time Limit: 4000/2000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) SubmitStatisticNext Problem Problem Description The kingdom of Flatland has n cities. Recently the king of Flatland visited Japan and was amazed by high

51Nod - 1629 B君的圆锥

51Nod - 1629 B君的圆锥 B君要用一个表面积为S的圆锥将白山云包起来. B君希望包住的白山云体积尽量大,B君想知道体积最大可以是多少. 注意圆锥的表面积包括底面和侧面. Input 一行一个整数,表示表面积S.(1 <= S <= 10^9) Output 一行一个实数,表示体积. Input示例 8 Output示例 1.504506 题解: 想使用三分法来解决,但是在9个test中只通过了第一个.(不知道出错在哪里了) 后转 直接公式法解决. #include <iost

HDU 4873 ZCC Loves Intersection(JAVA、大数、推公式)

在一个D维空间,只有整点,点的每个维度的值是0~n-1 .现每秒生成D条线段,第i条线段与第i维度的轴平行.问D条线段的相交期望. 生成线段[a1,a2]的方法(假设该线段为第i条,即与第i维度的轴平行)为,i!=j时,a1[j]=a2[j],且随机取区间[0,n-1]内的整数.然后a1[i],a2[i]在保证a1[i]<a2[i]的前提下同样随机. 由于D条线段各自跟自己维度的轴平行,我们可以转换成只求第i个维度与第j个维度的相交期望,然后乘以C(2,n)就好了 显然线段[a1,a2]和线段[

HDU 4870 Rating(概率、期望、推公式) &amp;&amp; ZOJ 3415 Zhou Yu

其实zoj 3415不是应该叫Yu Zhou吗...碰到ZOJ 3415之后用了第二个参考网址的方法去求通项,然后这次碰到4870不会搞.参考了chanme的,然后重新把周瑜跟排名都反复推导(不是推倒)四五次才上来写这份有抄袭嫌疑的题解... 这2题很类似,多校的rating相当于强化版,不过原理都一样.好像是可以用高斯消元做,但我不会.默默推公式了. 公式推导参考http://www.cnblogs.com/chanme/p/3861766.html#2993306 http://www.cn

sgu495:概率dp / 推公式

概率题..可以dp也可以推公式 抽象出来的题目大意: 有 n个小球,有放回的取m次  问 被取出来过的小球的个数的期望 dp维护两个状态 第 i 次取出的是 没有被取出来过的小球的 概率dp[i] 和取出的是已经被取出来过的小球的概率np[i]; 如果第 i-1 次取出的是已经被取出来过的小球 那么第 i 次取出没有取出来过小球的概率即为 dp[i-1]: 反之则为 dp[i-1] - 1/n(没有取出来过的小球少了一个) 所以可以得到状态转移方程 dp[i]=dp[i-1]*(dp[i-1]-

bjfu1211 推公式,筛素数

题目是求fun(n)的值 fun(n)= Gcd(3)+Gcd(4)+…+Gcd(i)+…+Gcd(n).Gcd(n)=gcd(C[n][1],C[n][2],……,C[n][n-1])C[n][k] means the number of way to choose k things from n things. n最大一百万,马上反映到可能是递推打表. 首先肯定是推公式了,fun(n)其实就是Gcd(n)的一个前n项和,没意义,直接看Gcd(n),把前几项列出来,发现公式是Gcd(n) =

HDU 1165 Eddy&#39;s research II (推公式)

Eddy's research II Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3122    Accepted Submission(s): 1137 Problem Description As is known, Ackermann function plays an important role in the sphere

hdu 6128 Inverse of sum(推公式)

题目链接:hdu 6128 Inverse of sum 题意: 给你n个数,问你有多少对i,j,满足i<j,并且1/(ai+aj)=1/ai+1/aj 在%p意义下. 题解: 不愧是高中生,推公式神题. 将式子通分化简后可得(ai2+aj2+ai*aj)%p=0. 然后两边同时将两边乘(ai-aj),化简可得(ai3-aj3)%p=0. 然后就可以用map记录一下个数,并且减掉ai==aj时不合法的情况就行了. 1 #include<bits/stdc++.h> 2 #define F