hdu多校第七场 1011 (hdu6656) Kejin Player 概率dp
题意:
一个游戏,有许多关,到下一关要花费金钱,做出尝试,有概率成功,若成功则到达下一关,若失败则停在此关或退回到前面某关,询问第l关到第r关的期望费用
题解:
显然,第r关到第l关的费用是dp[r]-dp[l]
那么如何算出dp数组呢?首先dp[1]=0,利用期望方程正推
假设i点,成功率为p,失败则跳到j,成功则跳到k,花费q,则期望方程为
dp[k]=dp[i]+p(q)+(1-p)(dp[k]-dp[j])
移项后递推即可
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef long long ll; typedef pair<int, LL>P; const int M = 4e5 * 4 + 5; const LL mod = 1e9 + 7; const LL lINF = 0x3f3f3f3f3f3f3f3f; #define ls (rt<<1) #define rs (rt<<1|1) LL gcd(LL a, LL b) { return b ? gcd(b, a%b) : a; } LL quickpow(LL a, LL b, LL mod) { LL res = 1; while (b) { if (b & 1) res = (res*a) % mod; a = (a*a) % mod; b >>= 1; } return res; } inline int read() { int x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = 10 * x + ch - '0'; ch = getchar(); } return x * f; } inline ll readll() { ll x = 0, f = 1; char ch = getchar(); while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); } while (ch >= '0' && ch <= '9') { x = 10 * x + ch - '0'; ch = getchar(); } return x * f; } int n, q; LL r[M], s[M], x[M], a[M], dp[M]; int main() { int t = read(); while (t--) { n = readll(); q = readll(); for (int i = 1; i <= n; i++) { r[i] = readll(); s[i] = readll(); x[i] = readll(); a[i] = readll(); } dp[2] = quickpow(r[1], mod - 2, mod)*a[1] % mod*s[1] % mod; for (int i = 2; i <= n; i++) { LL tmp = ((a[i] + (s[i] - r[i])*quickpow(s[i], mod - 2, mod) % mod*(dp[i] - dp[x[i]] + mod) % mod) % mod) % mod*s[i] % mod * quickpow(r[i], mod - 2, mod) % mod; dp[i + 1] = (dp[i] + tmp) % mod; } while (q--) { int l, r; l = read(); r = read(); printf("%lld\n", (dp[r] - dp[l] + mod) % mod); } } }