J - Kejin Player HDU - 6656

J - Kejin Player

HDU - 6656

https://vjudge.net/contest/349029#problem/J

题目描述:

花费a[i],从i升到i+1级有p[i]的可能成功,失败就掉到x[i]级。问从l升到r级的期望。

分析:

dp[i]表示从1级升到i级的期望,如果要计算j升到i级,就算dp[i]-dp[j]。因为他只能一级一级升,所以从1到i,一定会经过j。

dp[i]转移到dp[i+1],假设他经过t次后成功,那么前t-1次就是失败的,就要重新从x[i]升到i,重复t-1次。x[i]升到i的期望可以知道是dp[i]-d[x[i]]。

得到方程:dp[i+1]=dp[i]+a[i]+(t-1) * (dp[i]-dp[x[i]]+mod)+(t-1) * a[i];

左边,dp[i]+a[i]是成功,右边是失败。

因为成功概率为1/t=p[i]=r[i]/s[i]。可以求出t=s[i]/r[i],再带回上式。除法取模再用下逆元。

代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int maxn=5e5+6;
ll dp[maxn];
ll mp(ll x,ll n)
{
    ll res=1;
    while(n)
    {
        if(n&1) res=res*x%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,q;
        scanf("%d%d",&n,&q);
        ll x[n+6],a[n+6],r[n+6],s[n+6];
        for(int i=1;i<=n;i++) 
        {
            scanf("%lld %lld %lld %lld",&r[i],&s[i],&x[i],&a[i]);
        }
        memset(dp,0,sizeof dp);
        for(int i=1;i<=n;i++)
        {
            ll t=s[i]*mp(r[i],mod-2)%mod;
            dp[i+1]=dp[i]+a[i]+(dp[i]-dp[x[i]]+mod)%mod*(t-1)%mod+(t-1)%mod*a[i]%mod;
            dp[i+1]%=mod;
        }
        for(int i=1;i<=q;i++)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%lld\n",(dp[r]-dp[l]+mod)%mod);
        }
    }   
    return 0;
}
 

 

posted on 2020-03-09 18:17  Aminers  阅读(191)  评论(0编辑  收藏  举报

导航