2019多校第六场1101(HDU6656)

Kejin Player:

2019多校第六场1101(HDU6656)_第1张图片题意:从1级氪金升级到n+1级,每一次升级需要花费a元,有r / s的几率成功,如果失败了掉回x级,q个询问,输出询问从l级升到r级需要多少钱。

思路:假设尝试r / s次之后必定已经成功升级,升级成功只升一次就够了,所以失败的次数为r / s - 1,因此升级所需要的钱就是到达第 i 层需要的金钱 + 失败的次数 * 每次失败要花费的钱 + 成功所需要花费的钱* 成功的次数即1次。而失败要花费的钱是:假设当前在 i 层, 升级到i + 1层,如果失败返回 x 层,则失败的话需要的花费是尝试升级的钱a元 + 从x层回到 i 层要花的钱,因为是递推得到的花费所以 x 层到 i 层的花费类似前缀和直接ex[i] - ex[x],所以递推的公式就很明了了:ex[i + 1] = ex[i] + (r / s - 1) * (ex[i] - ex[x] + a) + a;再注意一下取模就好了,因为不能直接对分数取模,因此用逆元来计算分数。

AC代码:

/*---------------------------------
File name: 1011.cpp
Team: 这题太简单啦
Author: Snpilola
Creation date: 2019-08-13 14:19
---------------------------------*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define pb push_back
#define LL long long
#define mkp make_pair
#define lowbit(x) x & (-x)
#define PII pair
#define Pque priority_queue 
using namespace std;
const int maxn = 5e5 + 5;
const int inf = 0x3f3f3f3f;
const LL mod = 1e9 + 7;

LL ex[maxn];

LL fpow(LL x, LL y){
	LL ans = 1;
	while(y){
		if(y & 1) ans = ans * x % mod;
		x = x * x % mod;
		y >>= 1;
	}
	return ans;
}

int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		int n, q;
		scanf("%d %d", &n, &q);
		ex[0] = 0, ex[1] = 0;
		for(int i = 1; i <= n; i++){
			LL r, s, x, a;
			scanf("%lld %lld %lld %lld", &r, &s, &x, &a);
			LL pos = (((s - r) * fpow(r, mod - 2) % mod) * ((ex[i] - ex[x] + a + mod) % mod) % mod + a) % mod;
			ex[i + 1] = ex[i] + pos;
		}
		for(int i = 1; i <= q; i++){
			int l, r;
			scanf("%d %d", &l, &r);
			printf("%lld\n", (ex[r] - ex[l] + mod) % mod);
		}
	}
	return 0;
}

 

你可能感兴趣的:(题解)