http://acm.hdu.edu.cn/showproblem.php?pid=6656
题意:有一个闯关,从第i关到第i+1关,需要花费a[i]钱做一次尝试,成功的概率为p[i],成功就到i+1关,否则就退回到x[i]关。给q个询问,每次给L和R,求关L到关R的期望花费的钱。
思路:
肯定是一关关依次走,假设dp[i]为从第一关到第i关需要花费的期望,那么满足(L到R的期望)=dp[R]-dp[L]。
然后考虑dp[i],考虑第i关直接通过或者不通过。(x为x[i])
移项得:
/* (o O o)
* Author : Rshs
* Data : 2019-08-28-18.53
*/
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LL mod = 1e9+7;
const int MX = 1e6+5;
int r[MX],s[MX],x[MX],a[MX];
LL dp[MX];
void exgcd(LL a,LL b,LL &x,LL &y,LL &d){ //欧几里得函数 求解ax+by=gcd(a,b)的一组解 d=gcd(a,b)
if(b==0){d=a,x=1,y=0;return;}
exgcd(b,a%b,y,x,d); //x=y0,y=x0-a/b*y0
y-=x*(a/b);
}
LL inv(LL t, LL p){ //返回t对p的逆元
LL d,x,y;
exgcd(t,p,x,y,d);
return (x%p+p)%p; //x可能为负,也可能过大
}
void Main(){
int n,q;cin>>n>>q;
for(int i=1;i<=n;i++)scanf("%d%d%d%d",&r[i],&s[i],&x[i],&a[i]);
dp[1]=0;
for(int i=2;i<=n+1;i++) dp[i]=((dp[i-1]+(LL)a[i-1]-dp[x[i-1]])%mod*(LL)s[i-1]%mod*inv(r[i-1],mod)%mod+dp[x[i-1]])%mod;
while(q--){
int l,r;scanf("%d%d",&l,&r);
cout<<((dp[r]-dp[l])%mod+mod)%mod<<'\n';
}
}
int main(){
int ca;cin>>ca;while(ca--)Main();
return 0;
}