HDU 6656 Kejin Player

本文探讨了一款游戏中的付费升级机制,玩家从第i级升级到第i+1级时,不仅需要支付一定金额,还要面对升级成功的概率。文章详细解析了如何计算玩家从某一等级升级到目标等级所需花费的平均金额,通过建立数学模型,运用概率论和期望值理论,最终实现了对升级成本的有效估算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Kejin Player

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 ai RMB to get to level i+1”. Cuber QQ now changed it a little bit: “when you are level i, you pay ai RMB, are you get to level i+1 with probability pi; otherwise you will turn into level xi (xi≤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≤n≤500 000) and q (1≤q≤500 000) in the first line, meaning the total number of levels and the number of queries.

Then follows n lines, each containing integers ri, si, xi, ai (1≤ri≤si≤109, 1≤xi≤i, 0≤ai≤109), space separated. Note that pi is given in the form of a fraction risi.

The next q lines are q queries. Each of these queries are two space-separated integers l and r (1≤l<r≤n+1).

The sum of n and sum of q from all t test cases both does not exceed 106.

Output
For each query, output answer in the fraction form modulo 109+7, that is, if the answer is PQ, you should output P⋅Q−1 modulo 109+7, where Q−1 denotes the multiplicative inverse of Q modulo 109+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

Hint
Huge IO (Over 40MB)! IO optimization is preferred.

题意
从1开始升级,从i升到i+1,需要aia_iai的钱,aia_iai必花,但是只有pip_ipi的概率升级到i+1i+1i+1,还有1−pi1-p_i1pi的概率降到xix_ixi级。qqq次询问,求从lllrrr的花费的钱的期望。

题解
挺没意思的一道题,我也很绝望,先是还没想就被队友灌输了一个用f(i)f(i)f(i)表示1−i1-i1i的期望的思想,然后顺着这个思路推了两个多小时,怎么想怎么不对,然后从零开始重新想
f(i+1)f(i+1)f(i+1)表示从iii升级到i+1i+1i+1的期望,sumisum_isumi表示从111iii的期望。
所以式子为
f(i+1)=piai+(1−pi)(f(i+1)+ai+sumi−sumxi)f(i+1)=p_ia_i+(1-p_i)(f(i+1)+a_i+sum_i-sum_{x_i})f(i+1)=piai+(1pi)(f(i+1)+ai+sumisumxi)
sumi+1=sumi+f(i+1)sum_{i+1}=sum_i+f(i+1)sumi+1=sumi+f(i+1)
升级到i+1i+1i+1pip_ipi的几率只花费aia_iai1−pi1-p_i1pi的几率降到xix_ixi,然后回升到iii的期望是sumi−sumxisum_i-sum_{x_i}sumisumxi,再加上从iii升级到i+1i+1i+1的期望和必花的aia_iai

最后就是,我一开始想到了每次求概率直接求逆元,但是沙雕的sumi−sumxisum_i-sum_{x_i}sumisumxi没加MODMODMOD,WA了后开始怀疑自己分数不能前面求逆元,然后写了发分数求和差,求出结果再取逆元,想想可能爆long long,还开心的弄了__int128。最后T到怀疑人生,又开始优化,果然我还是菜。

代码

#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <cmath>
#include <ctime>
using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define MIN(x,y) (x) < (y) ? (x) : (y)
#define MAX(x,y) (x) > (y) ? (x) : (y)
#define SGN(x) ((x)>0?1:((x)<0?-1:0))
#define ABS(x) ((x)>0?(x):-(x))
// #define int __int128

typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

const ll maxn = 5e5+10;
const ll INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
const int eps = 1e-8;

ll readll() {
  ll x = 0, w = 1;
  char ch = 0;
  while (ch < '0' || ch > '9') {  // ch 不是数字时
    if (ch == '-') w = -1;        // 判断是否为负
    ch = getchar();               // 继续读入
  }
  while (ch >= '0' && ch <= '9') {  // ch 是数字时
    x = x * 10 + (ch - '0');  // 将新读入的数字’加’在 x 的后面
    // x 是 ll 类型,char 类型的 ch 和 ’0’ 会被自动转为其对应的
    // ASCII 码,相当于将 ch 转化为对应数字
    // 此处也可以使用 (x<<3)+(x<<1) 的写法来代替 x*10
    ch = getchar();  // 继续读入
  }
  return x * w;  // 数字 * 正负号 = 实际数值
}

ll qpow(ll a,ll b,ll p){
    ll ans = 1;
    while(b){
        if(b&1) ans = ans*a%p;
        a = a*a%p;
        b >>= 1;
    }
    return ans;
}

ll r[maxn],s[maxn],x[maxn],a[maxn];
ll f[maxn],sum[maxn];
int main(){
    // ios::sync_with_stdio(false);
    ll t;t=readll();
    while(t--){
        ll n,q;
        // cin>>n>>q;
        n=readll(),q=readll();
        for(int i = 1; i <= n; ++i){
            r[i]=readll(),s[i]=readll(),x[i]=readll(),a[i]=readll();
        }
        f[0]=f[1]=0,sum[0]=sum[1]=0;
        for(int i = 1; i <= n; ++i){
            ll res = a[i]*r[i]+(s[i]-r[i])*(a[i]+sum[i]-sum[x[i]]+MOD)%MOD;
            res = (res + MOD)%MOD;
            f[i+1]=res*qpow(r[i],MOD-2,MOD)%MOD;
            sum[i+1] = sum[i]+f[i+1];
            sum[i+1] %= MOD;
        }
        for(int i = 1; i <= q; ++i){
            ll l,r;scanf("%lld%lld",&l,&r);
            printf("%lld\n",(sum[r]-sum[l]+MOD)%MOD);
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值