Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
The jackpot probability is chosen once and then fixed forever. So outcomes are not just wins/losses - they are information about which hidden was picked.
After seeing jackpots and jinxes, candidate probability has weight proportional to . Since , only different belief states can appear.
Do not put current money into the DP state. The optimal future expected balance scales linearly with current balance, so each belief state only needs a multiplier.
For current balance and bet , the expected future balance has the form . That is linear in .
A linear function over integer bets is maximized at an endpoint. So Jack only ever needs to bet or go all-in. Yep, the optimal casino strategy is either patience or full send.
The hidden jackpot chance is fixed. If the owner picked probability , then every round uses that same . This means observations update Jack's belief. Treating each round as if the casino rerolls is the classic wrong turn here.
Belief states
Suppose Jack has seen jackpots and jinxes. For a candidate probability , the likelihood of this observation history is:
The exact order of the outcomes does not matter, only the counts. Let cnt[p] be how many indices have value . Define:
This is the total posterior weight of the state. Then the posterior probability that the next round is a jackpot is:
Similarly:
There are only states with , and , so this part is tiny.
Why the balance disappears
Let be the best expected final balance multiplier if Jack currently has 1 dollar, has seen wins and losses, and has rounds left.
Base case:
Now suppose Jack currently has balance and bets integer . By induction, after a win his future expected balance is:
and after a loss it is:
So the expected final balance is:
Rearrange it:
For this state, everything except is fixed. So this is just a linear function of .
Jack may choose any integer with . A linear function on that interval is maximized at an endpoint. No fancy fractional bet, no balance DP, no cursed 1000-dimensional nonsense. The optimal bet is always either:
Transition
If Jack bets , his balance stays the same, and he learns the outcome:
If Jack goes all-in, losing sends his balance to , so only the win branch contributes:
Therefore:
The answer is the expected final balance minus the initial 1000 dollars:
Unreachable states
If , that observation state is impossible under all candidate probabilities. Its DP value never matters. In code, set it to something harmless like 1 and skip division by zero. This matters for cases with or ; otherwise NaNs sneak in and ruin the party.
Complexity
There are states and only 101 possible probability values after compression. So the complexity is:
with tiny memory. For these limits, it basically runs before the slot machine finishes blinking.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int n, k;
cin >> n >> k;
vector<int> cnt(101, 0);
for (int i = 0; i < n; i++) {
int p;
cin >> p;
cnt[p]++;
}
vector<long double> q(101), r(101);
for (int p = 0; p <= 100; p++) {
q[p] = (long double)p / 100.0L;
r[p] = 1.0L - q[p];
}
vector<vector<long double>> sum(k + 2, vector<long double>(k + 2, 0.0L));
for (int w = 0; w <= k + 1; w++) {
for (int l = 0; l <= k + 1 - w; l++) {
long double cur = 0.0L;
for (int p = 0; p <= 100; p++) {
if (cnt[p] == 0) continue;
cur += (long double)cnt[p] * powl(q[p], w) * powl(r[p], l);
}
sum[w][l] = cur;
}
}
vector<vector<long double>> dp(k + 2, vector<long double>(k + 2, 1.0L));
for (int t = 1; t <= k; t++) {
vector<vector<long double>> ndp(k + 2, vector<long double>(k + 2, 1.0L));
for (int w = 0; w + t <= k; w++) {
for (int l = 0; w + l + t <= k; l++) {
long double s = sum[w][l];
if (s == 0.0L) {
ndp[w][l] = 1.0L;
continue;
}
long double win = sum[w + 1][l] / s;
long double lose = sum[w][l + 1] / s;
long double bet_zero = win * dp[w + 1][l] + lose * dp[w][l + 1];
long double all_in = 2.0L * win * dp[w + 1][l];
ndp[w][l] = max(bet_zero, all_in);
}
}
dp.swap(ndp);
}
long double profit = 1000.0L * (dp[0][0] - 1.0L);
cout << fixed << setprecision(20) << profit << '\n';
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int n, k;
cin >> n >> k;
vector<int> cnt(101, 0);
for (int i = 0; i < n; i++) {
int p;
cin >> p;
cnt[p]++;
}
vector<long double> q(101), r(101);
for (int p = 0; p <= 100; p++) {
q[p] = (long double)p / 100.0L;
r[p] = 1.0L - q[p];
}
vector<vector<long double>> sum(k + 2, vector<long double>(k + 2, 0.0L));
for (int w = 0; w <= k + 1; w++) {
for (int l = 0; l <= k + 1 - w; l++) {
long double cur = 0.0L;
for (int p = 0; p <= 100; p++) {
if (cnt[p] == 0) continue;
cur += (long double)cnt[p] * powl(q[p], w) * powl(r[p], l);
}
sum[w][l] = cur;
}
}
vector<vector<long double>> dp(k + 2, vector<long double>(k + 2, 1.0L));
for (int t = 1; t <= k; t++) {
vector<vector<long double>> ndp(k + 2, vector<long double>(k + 2, 1.0L));
for (int w = 0; w + t <= k; w++) {
for (int l = 0; w + l + t <= k; l++) {
long double s = sum[w][l];
if (s == 0.0L) {
ndp[w][l] = 1.0L;
continue;
}
long double win = sum[w + 1][l] / s;
long double lose = sum[w][l + 1] / s;
long double bet_zero = win * dp[w + 1][l] + lose * dp[w][l + 1];
long double all_in = 2.0L * win * dp[w + 1][l];
ndp[w][l] = max(bet_zero, all_in);
}
}
dp.swap(ndp);
}
long double profit = 1000.0L * (dp[0][0] - 1.0L);
cout << fixed << setprecision(20) << profit << '\n';
}