Codeforces
CF Step
Youtube Linkedin Discord Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Code : Black Jack

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

#define endl "\n";

void solve(int n, int L, int D) {
    auto p = (long double)1.0 / D;

    // ndp[i] is the probability that y is equal to i.
    vector<long double> ndp(n + 1, 0);
    ndp[0] = 1;
    for (int y = 0; y < L; y++) {
        for (int nxt = 1; nxt <= min(D, n - y); nxt++) {
            ndp[y + nxt] += p * ndp[y];
        }
        ndp[y] = 0;
    }
    for (int y = 1; y <= n; y++) {
        cout << ndp[y] << " ";
    }
    cout << endl;
    cout << endl;

    // win[i] is the winning probability when x = i.
    vector<long double> win(n + 1, 0);
    for (int x = 0; x <= n; x++) {
        // You would lose if max(L, i) <= y <= n.
        long double ndpsum = 0;
        for (int y = max(L, x); y <= n; y++) {
            ndpsum += ndp[y];
        }
        win[x] += (1 - ndpsum);
    }
    for (int x = 1; x <= n; x++) {
        cout << win[x] << " ";
    }
    cout << endl;
    cout << endl;

    long double ans = 0;

    // Strategy : No more rolls after x >= lim.
    for (int lim = 1; lim <= n; lim++) {
        // dp[i] is the probability that x = i in this strategy.
        vector<long double> dp(n + 1, 0);
        dp[0] = 1;
        for (int x = 0; x < lim; x++) {
            for (int nxt = 1; nxt <= min(D, n - x); nxt++) {
                dp[x + nxt] += p * dp[x];
            }
            dp[x] = 0;
        }
        for (int x = 1; x <= n; x++) {
            cout << dp[x] << " ";
        }
        cout << endl;

        // cur is the winning probability for this strategy.
        long double cur = 0;
        for (int x = 1; x <= n; x++) {
            cur += dp[x] * win[x];
        }
        cout << cur << endl;
        cout << endl;
        ans = max(ans, cur);
    }

    cout << ans << endl;
}

int main() {
    cout << fixed << setprecision(10);

    int t;
    cin >> t;
    for (int i = 0; i < t; i++) {
        int n, L, D;
        cin >> n >> L >> D;
        solve(n, L, D);
    }

    return 0;
}
#include <atcoder/segtree>
#include <bits/stdc++.h>

using namespace std;
using namespace atcoder;

#define endl "\n";

long double op(long double a, long double b) { return a + b; }

long double e() { return 0; }

class BlackBox {
  public:
    segtree<long double, op, e> *diff_array;
    BlackBox(int n) { diff_array = new segtree<long double, op, e>(n); }

    void range_inc(int l, int r, long double delta) {
        diff_array->set(l, diff_array->get(l) + delta);
        diff_array->set(r + 1, diff_array->get(r + 1) - delta);
    }

    long double point_query(int idx) {
        // Atcoder's segtree prod function has range [l, r).
        // Hence, we add + 1 to make inclusive range.
        return diff_array->prod(0, idx + 1);
    }
};

void solve(int n, int L, int D) {
    auto p = (long double)1.0 / D;

    // ndp[i] is the probability that y is equal to i.
    vector<long double> ndp(n + 1, 0);
    ndp[0] = 1;
    for (int y = 0; y < L; y++) {
        for (int nxt = 1; nxt <= min(D, n - y); nxt++) {
            ndp[y + nxt] += p * ndp[y];
        }
        ndp[y] = 0;
    }
    for (int y = 1; y <= n; y++) {
        cout << ndp[y] << " ";
    }
    cout << endl;
    cout << endl;

    // win[i] is the winning probability when x = i.
    vector<long double> win(n + 1, 0);
    for (int x = 0; x <= n; x++) {
        // You would lose if max(L, i) <= y <= n.
        long double ndpsum = 0;
        for (int y = max(L, x); y <= n; y++) {
            ndpsum += ndp[y];
        }
        win[x] += (1 - ndpsum);
    }
    for (int x = 1; x <= n; x++) {
        cout << win[x] << " ";
    }
    cout << endl;
    cout << endl;

    long double ans = 0;

    // Strategy : No more rolls after x >= lim.
    for (int lim = 1; lim <= n; lim++) {
        // dp[i] is the probability that x = i in this strategy.
        BlackBox dp(n + 5);
        dp.range_inc(0, 0, 1);
        for (int x = 0; x < lim; x++) {
            dp.range_inc(x + 1, x + min(D, n - x), p * dp.point_query(x));
            dp.range_inc(x, x, -dp.point_query(x));
        }
        for (int x = 1; x <= n; x++) {
            cout << dp.point_query(x) << " ";
        }
        cout << endl;

        // cur is the winning probability for this strategy.
        long double cur = 0;
        for (int x = 1; x <= n; x++) {
            cur += dp.point_query(x) * win[x];
        }
        cout << cur << endl;
        cout << endl;
        ans = max(ans, cur);
    }

    cout << ans << endl;
}

int main() {
    cout << fixed << setprecision(10);

    int t;
    cin >> t;
    for (int i = 0; i < t; i++) {
        int n, L, D;
        cin >> n >> L >> D;
        solve(n, L, D);
    }

    return 0;
}