牛客练习74-E-CCA的期望-数学,概率

题目大意:

给你一张n个白点m边的带权无向图。一次你可以选择两个点,将他们之间的最短路上的点都染成黑色(如有多条,都染成黑色).问你k次之后期望有多少个点染成黑色.
n , m ≤ 500 , k , w ≤ 1 e 9 n,m \leq 500 , k,w\leq 1e9 n,m500,k,w1e9

题目思路:

这个题目关键要知道两个点:
1.期望的独立性:一个点是否变黑色与其他点没有关系,并且两次染色之间也没有互相影响,所以我们可以对每个点进行独立计算.

2.期望=概率:由于点之间独立,所以我们就是求每个点在k次之后变成黑色的期望的累和.由于这里的期望不带权值,所以期望就是概率..然后正难则反,我们只要求[一次不变黑]的概率的 k k k次方即可.

那么我们先floyd跑一跑最短路,然后求每个点有多少条最短路经过.之后 O ( n ) O(n) O(n)计算即可.

AC代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 500 + 5;
const int mod = 1023694381;
ll a[maxn] , dp[maxn][maxn] , cnt[maxn];
ll ksm (ll a , ll b){ ll ans = 1 , base = a;
while (b){if (b & 1) ans = ans * base % mod;b >>= 1;base = base * base % mod;}return ans;}
int main()
{
    ios::sync_with_stdio(false);
    ll n , m , k; cin >> n >> m >> k;
    for (int i = 1 ; i <= n ; i++){
        cin >> a[i];
    }
    memset(dp , -1 , sizeof dp);
    for (int i = 1 ; i <= n ; i++){
        dp[i][i] = 0;
    }
    for (int i = 1 ; i <= m ; i++){
        int x , y , z; cin >> x >> y >> z;
        dp[x][y] = dp[y][x] = z;
    }
    for (int k = 1 ; k <= n ; k++){
       for (int i = 1 ; i <= n ; i++){
            for (int j = 1 ; j <= n ; j++){
                if (dp[i][k] == -1 || dp[k][j] == -1) continue;
                if (dp[i][j] == -1 || dp[i][j] > dp[i][k] + dp[k][j])
                    dp[i][j] = dp[i][k] + dp[k][j];
            }
       }
    }
    for (int k = 1 ; k <= n ; k++){
       for (int i = 1 ; i <= n ; i++){
            for (int j = 1 ; j <= n ; j++){
                if (i == j) continue;
                if (dp[i][j] == dp[i][k] + dp[k][j])
                    cnt[k]++;
            }
       }
    }
    ll ans = 0 , g = n * (n - 1);
    ll inv = ksm(g , mod - 2);
    for (int i = 1 ; i <= n ; i++){
        if (a[i] == 1) {
            ans++;
            continue;
        }
        ll res = (g - cnt[i]) * inv % mod;
        res = ksm(res , k);
        res = (1 - res + mod) % mod;
        ans = (ans + res) % mod;
    }
    cout << ans << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值