CF Round 926(Div. 2)[C. Sasha and the Casino][https://codeforces.com/contest/1929/problem/C ] 【博弈论 思维】
一道博弈论思维好题
本蒟蒻语言组织薄弱,请嘴下留情[/(ㄒoㄒ)/]
题意:
赌博。初始钱a 最多会输x次 会有大保底让你在x + 1次必赢。
输了,投的钱没有;
赢了,可获得k倍钱(即增加了k-1倍投入钱且投入钱返回)
判断是否可以赚到任意钱。
思路:
看作是和赌场老板的博弈,并且我们都知道大保底这件事,这是共识。
在投钱x次的过程中,我们一定要让他不让我们赢,因为如果在输x次中赢了一次,那么将重新开始,如果这是输钱的操作那么我们永不可能赢(这肯定是输钱的,因为如果我们赢钱,老板一定不会让我们赢)。
所以我们要投的钱,一定是:如果我们赢了 并可以 追平失去的钱且+1,这样的话老板一定不会让我们赢。如果没有这么多钱来投入 保证 如果赢了可以赚钱的操作,那么老板一定让我们赢,这是一次输钱操作,然后又会回到当初,我们不会赢。如果我们成功连续输掉x次,在第x+1次,我们必赢,所以一定会全盘投入,如果这次赚到钱不如起始钱,那么我们不可能赢,反之即赢。
代码如下:
#include <bits/stdc++.h>
using namespace std;
// 博弈论
using ll = long long;
const int maxn = 2e6 + 5;
void solve() {
ll k, x, a;
cin >> k >> x >> a;
ll temp = a; // 临时变量
ll sum = 0; // 之前已经输的钱
ll now = 0; // 此次要投的钱
for (int i = 1; i <= x + 1; i++) // 为什么k+1(下有)
{
if (i == x + 1) now = a; // k+1的原因
else now = sum / (k - 1)+ 1; // 每次投钱要保证 之前投的钱 要小于 这次获胜能赚到的钱
// 推导:
// sum + now < k * now
// now * (k - 1) > sum
// now > sum / (k - 1)
// => now = sum / (k - 1) + 1;
// 如果掏不出这么多钱 就输了
a -= now;
if (a < 0) {
cout << "No\n";
return ;
}
sum += now;
// cout << a << endl;
}
a += now * k;
if (a <= temp) cout << "No\n"; // 最后的钱<=原来的钱
else cout << "Yes\n";
return ;
}
int main() {
ios::sync_with_stdio(0);
int T;
cin >> T;
while (T--) solve();
}