计蒜客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;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值