2019杭电暑期多校第七场 (K)

K - Kejin Player

题目大意

  升级要钱 a i ai ai,升级有失败的概率 p i pi pi,而失败则会回到 x i xi xi级别。问:给定两个等级 l < r ll<r l l l升到 r r r的期望钱

解题思路:

  1. f [ i ] f[i] f[i] i i i i + 1 i + 1 i+1级别的期望钱, s u m [ i ] sum[i] sum[i] f [ 1 ] f[1] f[1] f [ i ] f[i] f[i]的期望钱的总和, q [ i ] q[i] q[i]为失败概率
  2. 首先假设当前 i i i层如果失败那么只会返回到 x i = i xi = i xi=i层,由求和式子(高中的错项相消法)可以得出当前 f [ i ] = a i / p i f[i] = ai / pi f[i]=ai/pi
  3. 再进一步假设返回的 x i = i − 1 xi = i - 1 xi=i1, 那么 f [ i ] = a i / p [ i ] + ( s u m [ i − 1 ] − s u m [ i − 2 ] ) ∗ q [ i ] f[i] = ai / p[i] + (sum[i - 1] - sum[i - 2]) * q[i] f[i]=ai/p[i]+(sum[i1]sum[i2])q[i]
  4. 然后我们大胆推结论 f [ i ] = a i / p [ i ] + ( s u m [ i − 1 ] − s u m [ x i − 1 ] ) ∗ q [ i ] f[i] = ai / p[i] + (sum[i - 1] - sum[xi - 1]) * q[i] f[i]=ai/p[i]+(sum[i1]sum[xi1])q[i]
  5. 最后因为要对 M o d = ( 1 e 9 + 7 ) Mod = (1e9 + 7) Mod=(1e9+7)取模,最后的式子即为f[i] = (a[i] * p[i] % Mod + (sum[i - 1] - sum[x[i] - 1] + Mod) * q[i] % Mod) % Mod;
  6. 为什么这里的期望符合累加呢?
      由于当到达一个点x时,你接下来要发生的事情与之前做的事情没有任何关联,无论你用何种方式到达x,你接下来的待遇都会被一视同仁,也就是我当前的决策对于将来没啥影响。(引用来源:博客)

AC代码

#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll Mod = 1000000007;
int T, n, m, r[500100], s[500100], x[500100], a[500100];
ll p[500100], f[500100], sum[500100], q[500100];
void Exgcd(ll a, ll b, ll & x, ll & y) {
    if(b == 0) x = 1, y = 0;
    else Exgcd(b, a % b, y, x), y -= a / b * x;
}
int main() {
    ll tx, ty;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++) scanf("%d%d%d%d", &r[i], &s[i], &x[i], &a[i]);
        for(int i = 1; i <= n; i++) {
            Exgcd(r[i], Mod, tx, ty);
            tx = (tx % Mod + Mod) % Mod;
            p[i] = s[i] * tx % Mod;
            q[i] = (s[i] - r[i]) * tx % Mod;
        }
        f[1] = a[1] * p[1] % Mod;
        sum[1] = f[1];
        for(int i = 2; i <= n; i++) {
            f[i] = (a[i] * p[i] % Mod + (sum[i - 1] - sum[x[i] - 1] + Mod) * q[i] % Mod) % Mod;//还要考虑失败的概率
            sum[i] = (sum[i - 1] + f[i]) % Mod;
        }
        while(m--) {
            scanf("%lld%lld", &tx, &ty);
            printf("%lld\n", (sum[ty - 1] - sum[tx - 1] + Mod) % Mod);
        }//加Mod是为了防止出现负数
    }
    return 0;
}

你可能感兴趣的:(杭电多校)