首页 > 技术文章 > HDOJ-6656(数论+逆元)

GarrettWale 2019-08-14 17:12 原文

Kejin Player

HDOJ-6656

  • 设f[i]为从i升级到i+1期望需要的金钱,由于每级都是能倒退或者升级到i+1,所以询问从l,r的期望金钱可以直接前缀和,那么推导每一级升级需要的期望钱也可以用前缀和推导
  • 设sum[i]=f[1]+f[2]....f[i] ,那么从 l 升级到 r 就是sum[r-1]-sum[l-1]。
  • 对于f[i] ,有p的概率交钱直接变成i+1,有(1-p)的概率回到x级,那么回到x级后想要升级到i+1,需要sum[i-1]-sum[x-1]升回到i级,再+f[i]从i级打到i+1级
  • 所以可以列出方程  f[i]=pa[i]+(1-p)(sum[i-1]-sum[x-1]+f[i]+a[i]),//这里的是求期望
  • 原文链接:https://blog.csdn.net/liufengwei1/article/details/99326686
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const long long mod=1e9+7;
long long sum[500005];
long long dp[500005];
long long quick_mod(long long a,long long b){
    long long ans=1;
    a=a%mod;
    while(b>0){
        if(b%2==1)
            ans=ans*a%mod;
        b=b/2;
        a=(a*a)%mod;
    }
    return ans%mod;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    while(t--){
        int n,q;
        cin>>n>>q;
        long long r,s,x,a;
        sum[0]=dp[0]=0;
        for(int i=1;i<=n;i++){
            cin>>r>>s>>x>>a;
            int p=r*quick_mod(s,mod-2)%mod;
            dp[i]=(a+(1-p+mod)%mod*(a+sum[i-1]-sum[x-1]+mod)%mod*quick_mod(p,mod-2)%mod)%mod;
            sum[i]=(sum[i-1]+dp[i]+mod)%mod;
        }
        for(int i=0;i<q;i++){
            int l,r;
            cin>>l>>r;
            long long ans=(sum[r-1]-sum[l-1]+mod)%mod;
            cout<<ans<<endl;
        }
    }
    return 0;
}

推荐阅读