2019 杭電多校 7 1011
題目鏈接:HDU 6656
比賽鏈接:2019 Multi-University Training Contest 7
Problem Description
Cuber QQ always envies those Kejin players, who pay a lot of RMB to get a higher level in the game. So he worked so hard that you are now the game designer of this game. He decided to annoy these Kejin players a little bit, and give them the lesson that RMB does not always work.
This game follows a traditional Kejin rule of "when you are level i, you have to pay \(a_i\) RMB to get to level \(i+1\)". Cuber QQ now changed it a little bit: "when you are level \(i\), you pay \(a_i\) RMB, are you get to level \(i+1\) with probability \(p_i\); otherwise you will turn into level \(x_i (x_i\le i)\)".
Cuber QQ still needs to know how much money expected the Kejin players needs to ``ke'' so that they can upgrade from level \(l\) to level \(r\), because you worry if this is too high, these players might just quit and never return again.
Input
The first line of the input is an integer t, denoting the number of test cases.
For each test case, there is two space-separated integers \(n (1\le n\le 500 000)\) and \(q (1\le q\le 500 000)\) in the first line, meaning the total number of levels and the number of queries.
Then follows \(n\) lines, each containing integers \(r_i, s_i, x_i, a_i\) \((1\le r_i\le s_i\le 10^9, 1\le x_i\le i, 0\le a_i\le 10^9)\), space separated. Note that \(p_i\) is given in the form of a fraction \(\frac{r_i}{s_i}\).
The next \(q\) lines are \(q\) queries. Each of these queries are two space-separated integers \(l\) and \(r\) \((1\le l < r\le n+1)\).
The sum of \(n\) and sum of \(q\) from all \(t\) test cases both does not exceed \(10^6\).
Output
For each query, output answer in the fraction form modulo \(10^9+7\), that is, if the answer is \(\frac{P}{Q}\), you should output \(P\cdot Q^{−1}\) modulo \(10^9+7\), where \(Q^{−1}\) denotes the multiplicative inverse of \(Q\) modulo \(10^9+7\).
Sample Input
1
3 2
1 1 1 2
1 2 1 3
1 3 3 4
1 4
3 4
Sample Output
22
12
Solution
題意:
從 \(i\) 級升級到 \(i + 1\) 級需要花費 \(a_i\) RMB,成功的概率為 \(p_i = \frac{r_i}{s_i}\),若失敗則降到 \(x_i\) 級,然后給出 \(q\) 個詢問求 \(l\) 級升級到 \(r\) 級花費的期望。
題解:
期望DP 逆元
設 \(g(l, r)\) 為 \(l\) 升到 \(r\) 的期望,這種期望滿足減法 \(g(l, r) = g(1, r) − g(1, l)\)。因為升級只能一級一級升, 所以要從 \(1\) 升級到 \(r\), 必然要經過 \(l\)。可以降維,用 \(dp[i]\) 表示從 \(1\) 升到 \(i\) 的期望,則 \(g(l, r) = dp[r] − dp[l]\)。
從 \(dp[i]\) 轉移至 \(dp[i + 1]\),假設嘗試了 \(t\) 次才成功,那么也就是前面 \(t - 1\) 次都是失敗的,所以下一狀態的花費為當前狀態的花費 + 成功的花費 + 失敗的花費 + 失敗后再次回到當前狀態的花費。於是:
又 \(\frac{t - 1}{t} = 1 - \frac{r_i}{s_i}\),即 \(t = \frac{s_i}{r_i}\)
於是狀態轉移方程為:
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 5e5 + 10;
const ll mod = 1e9 + 7;
ll r[maxn], s[maxn], x[maxn], a[maxn];
ll dp[maxn];
ll qmod(ll a, ll b, ll p) {
ll ans = 1;
while(b) {
if(b & 1) ans = (a * ans) % p;
a = (a * a) % p;
b >>= 1;
}
return ans;
}
int main() {
int T;
cin >> T;
while(T--) {
int n, q;
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; ++i) {
scanf("%lld%lld%lld%lld", &r[i], &s[i], &x[i], &a[i]);
ll t = (s[i] * qmod(r[i], mod - 2, mod)) % mod;
dp[i + 1] = (dp[i] + (t * a[i]) % mod + ((t - 1) * (dp[i] - dp[x[i]])) % mod + mod) % mod;
}
for(int i = 0; i < q; ++i) {
int l, r;
scanf("%d%d", &l, &r);
printf("%lld\n", (dp[r] - dp[l] + mod) % mod);
}
}
return 0;
}