根据CF908D做了一点更改,不知道哦是否正确
  • 板块学术版
  • 楼主cjwdyzxfblzs
  • 当前回复1
  • 已保存回复1
  • 发布时间2023/10/13 11:14
  • 上次更新2023/11/2 14:10:43
查看原帖
根据CF908D做了一点更改,不知道哦是否正确
817044
cjwdyzxfblzs楼主2023/10/13 11:14

根据CF908D改了一下

给定3个数字,k,pa,pb

每次有 papa+pb\frac{pa}{pa + pb} 的概率往后添加一个 a

每次有 pbpa+pb\frac{pb}{pa + pb} 的概率往后添加一个 b

当出现了 kk 个形如 ab 的 子串 时停止。

求出所需步数的期望数。

答案对 1e9 + 7 取模。

目前我的思路是:

f[i][0/1]f[i][0 / 1] 当前已经有了 ii 个子串,当前字符为 a or ba \space or \space b。

f[i][0]=f[i+1][1]+pa+pbpbf[i][1]=f[i][0]+pa+pbpaf[i][0] = f[i + 1][1] + \frac{pa + pb}{pb} \\ f[i][1] = f[i][0] + \frac{pa + pb}{pa}

然后倒着逆推。

第一个递推式:

f[i][0]=(f[i][0]+1)×papa+pb+(f[i+1][1]+1)pbpa+pbf[i][0] = (f[i][0] + 1) \times \frac{pa}{pa + pb} + (f[i + 1][1] + 1)\frac{pb}{pa + pb}

化简之后

f[i][0]=f[i+1][1]+pa+pbpbf[i][0] = f[i + 1][1] + \frac{pa + pb}{pb}

第二个递推式:

f[i][1]=(f[i][1]+1)×pbpa+pb+(f[i][0]+1)×papa+pbf[i][1] = (f[i][1] + 1) \times \frac{pb}{pa + pb} + (f[i][0] + 1) \times \frac{pa}{pa + pb}

化简之后

f[i][1]=f[i][0]+pa+pbpaf[i][1] = f[i][0] + \frac{pa + pb}{pa}
#include <bits/stdc++.h>
#define int long long
inline int rd(void) {
    int x = 0, f = 1; char ch = getchar();
    while (!isdigit(ch)) { if (ch == '-') ch = getchar(); }
    while (isdigit(ch)) { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
    return x * f;
}
inline void wt(int x) {
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) wt(x / 10);
    putchar(x % 10 + 48); 
}
using db = double;
const int N = 1e3, MOD = 1e9 + 7;
inline int qmi(int a, int b)
{
    int ans = 1;
    while (b) { if (b & 1) ans = ans * a % MOD; a = a * a % MOD; b >>= 1; }
    return ans;
}
int f[N][N];
auto main() -> signed
{
    int k = rd(), pa = rd(), pb = rd();
    int p0 = qmi(pa, MOD - 2) * (pa + pb) % MOD, 
        p1 = qmi(pb, MOD - 2) * (pa + pb) % MOD;
    for (int i = k - 1; i >= 0; i -- )
    {
        f[i][0] = f[i + 1][1] + p1;
        f[i][1] = f[i][0] + p0;
    }
    std::cout << f[0][1] + f[0][0] << std::endl;
    return 0;
}
2023/10/13 11:14
加载中...