概率期望训练

blog / 2024-07-20 / 原文

前言

因为本人概率期望方面知识的不足,导致比赛经常被期望题腐乳,同时也为了减轻队内数学手的压力,遂开此题单。希望能在网络赛之前写完30道以上吧。

选用了洛谷的xzy的概率期望题单

链接

P5104 红包发红包

容易推出第\(k\)个人的抢到的期望钱数为\(\frac {w}{{2}^{k}}\)

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int mod = 1e9 + 7;
int power(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1ll) res = res * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return res;
}
void solve() {
    int w, n, k;
    cin >> w >> n >> k;

    cout << w * power(power(2, k), mod - 2) % mod << "\n";

}
signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    t = 1;
    //std::cin >> t;

    while (t--) {
        solve();
    }

    return 0;
}

P6154 游走

要求所有路径长度的期望,假设所有路径的长度为\(S\),以及所有路径的个数为\(T\),已得所求的期望为\(\frac {S}{T}\)。因此,问题的关键点在于怎样求出\(S,T\),注意到是有向无环图,拓扑排序后跑\(dp\)即可

#include <bits/stdc++.h>
using namespace std;
#define int long long

const int mod = 998244353;

int power(int a, int b) {
    int res = 1;
    while (b) {
        if (b & 1ll) res = res * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return res;
}
void solve() {
    int n, m;
    cin >> n >> m;

    vector<vector<int>> g(n + 1);
    vector<int> deg(n + 1);
    for (int i = 1; i <= m; i ++) {
        int u, v;
        cin >> u >> v;
        g[u].push_back(v);
        deg[v] ++;
    }

    auto in = deg;
    queue<int> q;
    vector<int> len(n + 1), cnt(n + 1);
    for (int i = 1; i <= n; i ++) {
        cnt[i] = 1;
        if (!deg[i]) {
            q.push(i);
        }
    }

    while (q.size()) {
        int t = q.front();
        q.pop();
        for (auto v : g[t]) {
            --deg[v];
            cnt[v] = cnt[t] + cnt[v], cnt[v] %= mod;
            len[v] = len[v] + len[t] + cnt[t], len[v] %= mod;
            if (!deg[v]) q.push(v);
        }
    }
    int f = 0, d = 0;
    for (int i = 1; i <= n; i ++) {
        f += len[i], f %= mod;
        d += cnt[i], d %= mod;
    }
    cout << f * power(d, mod - 2) % mod;
}
signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    t = 1;
    //std::cin >> t;

    while (t--) {
        solve();
    }

    return 0;
}

SP1026 FAVDICE - Favorite Dice

\({dp}_{i}\)表示,已经投出了\(i\)面,投出\(n\)面的期望次数,所以\({dp}_{n}\)\(0\),答案为\({dp}_{0}\),所以为逆推

因为已经选了\(i\)个数,再选一个与已经选过的数不同的概率是\(\frac {n - i}{n}\),相同为\(\frac {i}{n}\)

于是可得\({f}_{i}=\frac {n-i}{n}{f}_{i+1}+\frac {i}{n}{f}_{i}+1\)

解的\({f}_{i}={f}_{i+1}+\frac {n}{n - i}\)

#include <bits/stdc++.h>
using namespace std;
#define int long long

void solve() {
    int n;
    cin >> n;

    //dp[i]表示当前已经有了i面被投到,还需要多少次使得n面被投到
    vector<double> dp(n + 1);
    dp[n] = 0;
    for (int i = n - 1; i >= 0; i --) {
        dp[i] = dp[i + 1] + 1.0 * n / (n - i);
    }
    cout << fixed << ' ' << setprecision(10) << dp[0] << "\n";
}
signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    t = 1;
    std::cin >> t;

    while (t--) {
        solve();
    }

    return 0;
}

P1297 [国家集训队] 单选错位

根据期望的线性性,可以单独考虑每一个题做对的期望

  • 所有可能的结果,共\({a}_{i} \times {a}_{i - 1}\)
  • 做对的结果,共\(min({a}_{i},{a}_{i-1})\)

所以做对第\(i\)题的概率为\({p}_{i}=\frac {min({a}_{i}, {a}_{i - 1})}{{a}_{i-1}\times {a}_{i}}=\frac {1}{max({a}_{i - 1}, {a}_{i})}\)

最后答案为\(\sum {p}_{i}\)

#include <bits/stdc++.h>
using namespace std;
#define int long long

void solve() {
    int n;
    cin >> n;

    int A, B, C;
    cin >> A >> B >> C;

    vector<int> a(n + 1);
    cin >> a[1];
    for (int i = 2; i <= n; i ++) {
        a[i] = (a[i - 1] * A + B) % 100000001;
    }
    for (int i = 1; i <= n; i ++) {
        a[i] = a[i] % C + 1;
    }

    a[0] = a[n];
    double ans = 0;
    for (int i = 1; i <= n; i ++) {
        ans += 1.0 / max(a[i - 1], a[i]);
    }
   
   
   
    cout << fixed << setprecision(3) << ans << "\n";
}
signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);

    int t;
    t = 1;
    // std::cin >> t;

    while (t--) {
        solve();
    }

    return 0;
}