2023年牛客暑假多校-1 - J.Roulette题解

传送门(lduoj)

题目描述

Walk Alone is playing roulette, a kind of gambling. For simplification, we assume its rules and steps as follows: 

  • The whole gambling process composes of many turns.
  • In the i-th turn:
  • Walk Alone can choose an integerx_i​ and pay x_i​ yuan as the wager.
  • If Walk Alone wins, he will get 2x_i​ yuan from the maker, which means he gains x_i​ yuan in this turn. Otherwise, the maker will devour the x_i​ yuan he has paid, which means he loses x_i​ yuan in this turn. The probability that Walk Alone wins is 0.5.

Walk Alone has nnn yuan initially, and he wants to earn an extra mmm yuan. He will use the following strategy to gamble:

  • In the first turn, Walk Alone pays 1 yuan as the wager, i.e., x_1 = 1.
  • If Walk Alone wins in the (i−1)-th turn, then x_i = 1. Otherwise, x_i=2x_{i-1}
  • At the beginning of each turn, if Walk Alone has at least (n+m) yuan, then he gets satisfied and quits the game. Otherwise, he must pay x_i​ yuan as the wager, and he will have to stop gambling if he has less than x_i​ yuan.

 Walk Alone's good friend, Kelin wants to exhort him not to gamble. Tell him the probability that he successfully earns an extra mmm yuan.

输入描述

The only line of the input contains two integers n\left ( 1\leq n \leq 10^9 \right ) and m\left ( 1\leq m \leq 10^9 \right ), indicating the initial amount of money and the amount of money Walk Alone wants to earn.

输出描述

Output the probability that Walk Alone successfully earns an extra mmm yuan modulo 998244353998244353. It can be shown that the answer can always be expressed as an irreducible fraction x/y, where x and y are integers and y \not\equiv 0(mod \ \ 998244353). Output such an integer a that 0\leq a < 998244353 and a⋅a\cdot y\equiv x(mod \ \ 998244353).

样例

输入:

2 2

输出:

623902721

输入:

5 30

输出:

79070907

思路:

根据题目意思,第一次1元,第二次2元,第三次4元,第五次8元,如果第8次赢了可以赚16元,减去之前的1+2+4+8正好是1元,可以推出,只要我赢一次,我就可以获得1元,假设我在开始输之前是n元,那么我不管输几次(但是要保证有钱输),只要我赢一次,我就有n+1元。

所以我们可以把赌博的过程划分成”输输输......赢“这样的周期循环,每一个周期结束就可以获得1元。所以这一个周期赢钱的概率用以下理论进行比较:

第一次就赢:\frac{1}{2},第一次输第二次赢:\frac{1}{2} \times \frac{1}{2},第一次和第二次都输第三次赢:\frac{1}{2} \times \frac{1}{2} \times \frac{1}{2}......

以此类推,假设我这一个周期可以玩r次,那么我这一个周期赢钱的概率就\frac{1}{2}+\frac{1}{4}+...+\frac{1}{2^r},这个值也就是1-\frac{1}{2^r}
这样我们就可以从n \sim n+m每隔1个单位计算一次,这m段的概率乘起来就是最终能赚到n+m元的概率。

下面一个问题就是我怎么知道我可以玩多少次。假设我现在有n元,我能玩的次数 r 必须要满足这个要求2^r - 1 \leq n,所以我最多能玩的次数就是\left \lfloor log_2(n+1) \right \rfloor

还有一个需要解决的问题:我们可以看到题目中m的范围是1\leq m \leq 10^9,所以我们就可以如果一个单位一个单位遍历肯定 T 飞了,所以我就想,有没有某些数,他求出来的次数是一样的。然后就发现当2^{r+1}-1 = n时间求出来的是最多能玩r+1次时间的最小值,那么2^{r+1}-1-1就是 r 次,所以就可以得出2^r-1\sim 2^{r+1}-2 这个区间是能玩 r 次的钱数,所以一共有2^r-1\sim 2^{r+1}-2+1 个钱数对应的是能玩 r 次,所以我们就可以将这个区间合并起来,最多玩 r 次赢一元的概率然后(2^r-1\sim 2^{r+1}-2+1) 的次方。

题目要求输出的是a\cdot y\equiv x(mod \ \ 998244353) 中的 a ,这个 a 就是x \times y^{-1}  ,根据刚才的式子求逆元就行

代码:

#include
using namespace std;
typedef long long ll;
const int mod = 998244353;
ll qmi(ll m,ll k,ll p)
{
    ll res = 1 % p, t = m;
    while (k)
    {
        if (k&1) res = res * t % p;
        t = t * t % p;
        k >>= 1;
    }
    return res;
}
int main()
{
    ll n,m;
    cin >> n >> m;
    m += n;
    ll ans = 1;
    while(n < m){
        ll cnt = log2(n + 1);
        ll l = n;
        ll r = min(m, (1ll << (cnt + 1)) - 1);
        ans = ans * qmi(mod + 1 - qmi((1ll << cnt), mod - 2,mod),r - n,mod) % mod;
        n = r;
    }
    cout << ans;
}

你可能感兴趣的:(算法)