2023“钉耙编程”中国大学生算法设计超级联赛(1)Umamusume
题目大意
"Makea newtrack"是"Umamusume"游戏的一种新模式。在游戏中,会有n轮来提升属性,每一轮可以选择休息、训练或者比赛。
休息:增加50TP
训练:消耗50TP并增加15速度点数(TP少于50将失败)
比赛:消耗50TP并增加100G(TP少于50将失败)
在第一轮中,你有100TP。
你可以在特殊商店中花费G来获得物品,特殊商店每6轮刷新可以购买的物品(第6轮将是最早购买物品的时间)。每种物品在商店中出现的概率为 p p p(它可以存在于商店中但不出售任何物品,且每种物品的数量只有一个)。不同的物品有不同的价格和功能:
物品名称 | 价格 | 功能 |
---|---|---|
TP药(L) | 100G | 增加100TP |
TP药(M) | 50G | 增加50TP |
TP药(S) | 25G | 增加25TP |
魔法书(L) | 100G | 增加15速度点数 |
魔法书(M) | 50G | 增加7速度点数 |
魔法书(S) | 25G | 增加3速度点数 |
喇叭 | 100G | 下一次训练速度点数将变为2倍 |
权重 | 200G | 下一次训练速度点数将消耗100TP,但变为3倍 |
(权重不能与喇叭同时使用)
每个物品可以购买多次,并且你可以在购买后的任何一轮中使用物品。你事先知道商店中所有的物品,并且你很聪明。你想要知道预期的速度点数。
输出答案模 1 0 9 + 7 10^9+7 109+7后的值。
有 t t t组数据。
1 ≤ t ≤ 10000 , 0 ≤ n ≤ 1 0 9 , 0 ≤ p < 1 0 9 + 7 1\leq t\leq 10000,0\leq n\leq 10^9,0\leq p< 10^9+7 1≤t≤10000,0≤n≤109,0≤p<109+7
题解
我们可以发现,用道具的收益不超过休息再训练的收益。那么,在一般情况下,我们可以在TP值超过 50 50 50时训练,不超过 50 50 50时休息。
当 n n n为偶数时,答案为 ( n / 2 + 1 ) × 15 (n/2+1)\times 15 (n/2+1)×15。
当 n n n为奇数时,轮流训练和休息会导致有一轮没有收益,我们考虑用比赛和道具来获得收益。
我们可以进行一次比赛,花费50TP获得100G,再用其中50G来购买一个加 50 50 50的体力药或者两个加 25 25 25的体力药,获得50TP并用其来训练。这样就能在消耗一个回合但不消耗体力的情况下得到50G。
50G在商店中可以增加 7 7 7速度点数一次或者增加 3 3 3速度点数两次。还要考虑商店中物品总共出现的次数。最后有四种可能:速度点数增加 7 7 7,速度点数增加 6 6 6,速度点数增加 3 3 3,速度点数不增加。
分别算出种情况的概率,最后相加即可。
code
#include<bits/stdc++.h>
using namespace std;
const long long mod=1000000007;
int tp;
long long n,p;
long long mi(long long t,long long v){
if(!v) return 1;
long long re=mi(t,v/2);
re=re*re%mod;
if(v&1) re=re*t%mod;
return re;
}
int main()
{
scanf("%d",&tp);
while(tp--){
scanf("%lld%lld",&n,&p);
if(!n){
printf("0\n");
continue;
}
if(n<6){
printf("%lld\n",(n/2+1)*15);
continue;
}
if(n%2==0){
printf("%lld\n",(n/2+1)*15%mod);
}
else{
int t=n/6;
long long v1,v2,vt,k1,k2,k3,k4,ans;
v1=(1-mi(1-p+mod,t)+mod)%mod;//有一个或以上的这类物品的概率
v2=(1-(mi(1-p+mod,t)+mi(1-p+mod,t-1)*p%mod*t%mod)%mod+mod)%mod;//有两个或以上的这类物品的概率
vt=(1-(1-v1)*(1-v2)%mod+mod)%mod;//有体力药的概率
k1=vt*v1%mod;//第一种可能
k2=vt*mi(1-p+mod,t)%mod*v2%mod;//第二种可能
k3=vt*mi(1-p+mod,t)%mod*mi(1-p+mod,t-1)%mod*p%mod*t%mod;//第三种可能
k4=(1-(k1+k2+k3)%mod+mod)%mod;//第四种可能
ans=(15*(n/2)+22)*k1%mod+(15*(n/2)+21)*k2%mod+(15*(n/2)+18)*k3%mod+(15*(n/2)+15)*k4%mod;//统计答案
ans=ans%mod;
printf("%lld\n",ans);
}
}
return 0;
}