计蒜客2018蓝桥A模拟赛(一) 蒜头君王国(概率计算)

题目:

有一天,蒜头君当上了国王。蒜头君的王国有 n 坐城市,现在他需要在城市之间修建道路使得城市之间相互联通。

蒜头君是一个不会规划的人,他不知道哪些城市之间必须要有道路,所以对于任意两座城市之间,蒜头军会修建道路的概率为 p。

请你计算一下最后修建出来的道路使得 n 坐城市都联通的概率。
1 <= n <= 20

分析:

F(n) 表示 n 个点联通的概率,G(n) 表示 n 个点不联通的概率。

考虑第 n 个点和之前已有的 n1 个点中的 k1 个点有边,那么选出这 k1 个点组合为 Ck1n1 。这 k 个点联通的概率为 F(k)Ck1n1 。还剩 nk 个点,这 nk 个点和 k 个点不再连边,概率为 (1p)k(nk)

所以 G(n)=Ck1n1F(k)(1p)k(nk)

代码:

#include <bits/stdc++.h>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
#define lson rt*2,l,(l+r)/2
#define rson rt*2+1,(l+r)/2+1,r
typedef unsigned long long ull;
typedef long long ll;
const double EPS = 1e-8;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int MAXN = 25;
double ans[MAXN],p;
int n;

ll C(int n, int m) {
    ll ret = 1;
    for (int i = m + 1; i <= n; i++) {
        ret *= i;
    }
    for (int i = 1; i <= n-m; i++) {
        ret /= i;
    }
    return ret;
}

double Pow(double x, int m) {
    double ret = 1.0;
    while (m) {
        if (m & 1) {
            ret = ret * x;
        }
        x = x * x;
        m >>= 1;
    }
    return ret;
}

int main() {
    ios::sync_with_stdio(false);
    cin >> n >> p;
    ans[1] = 1.0;
    ans[2] = p;
    for (int i = 3; i <= n; i++) {
        ans[i] = 1.0;
        for (int k = 1; k <= i - 1; k++) {
            ans[i] -= C(i - 1, k - 1) * ans[k] * Pow(1.0 - p, k * (i - k));
        }
    }
    cout << fixed << setprecision(7) << ans[n] << endl;
    return 0;
}
阅读更多
上一篇计蒜客2018蓝桥A组模拟赛(一)青出于蓝胜于蓝(dfs序+线段树)
下一篇2018宁夏邀请赛网赛 G.Trouble of Tyrant(单调栈)
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭