考试时没注意这个题面长题里还有表格的题,而且过的人不多,就没开这道题。但其实这个题理解了题意之后很好过,难点在于翻译并理解题里给的游戏规则。
**题意:**有个游戏, T P TP TP是血量, G G G是金币, s p e e d p o i n t s speed\,\,points speedpoints是你的得分,最后目标是让这个 p o i n t point point最大。
你有三种操作 r e s t : + 50 T P , t r a i n : − 50 T P + 15 s p e e d p o i n t s , r a c e : − 50 H P + 100 G rest:+50TP,train:-50TP+15speed\,\,points,race:-50HP+100G rest:+50TP,train:−50TP+15speedpoints,race:−50HP+100G
你还有个商店,有如下商品:
T P M e d i c i n e ( L ) : − 100 G + 100 T P , T P M e d i c i n e ( M ) : − 50 G + 50 T P , T P M e d i c i n e ( s ) : − 25 G + 25 T P TP\,\,Medicine(L):-100G+100TP,TP\,\,Medicine(M):-50G+50TP,TP\,\,Medicine(s):-25G+25TP TPMedicine(L):−100G+100TP,TPMedicine(M):−50G+50TP,TPMedicine(s):−25G+25TP。
M a g i c B o o k ( L ) : − 100 G + 15 s p e e d p o i n t s , M a g i c B o o k ( M ) : − 50 G + 7 s p e e d p o i n t s , M a g i c B o o k ( L ) : − 25 G + 3 s p e e d p o i n t s Magic\,\,Book(L):-100G+15speed\,\,points,Magic\,\,Book(M):-50G+7speed\,\,points,Magic\,\,Book(L):-25G+3speed\,\,points MagicBook(L):−100G+15speedpoints,MagicBook(M):−50G+7speedpoints,MagicBook(L):−25G+3speedpoints。
H o r n : − 100 G , Horn:-100G, Horn:−100G,下次训练 s p e e d p o i n t s × 2 , W e i g h t : − 200 G speed\,\,points\times2,Weight:-200G speedpoints×2,Weight:−200G下次训练 − 100 T P , s p e e d p o i n t s × 3 -100TP,speed\,\,points\times 3 −100TP,speedpoints×3。
有 n n n轮操作,每轮可以进行一个操作,体力不能为负,但是可以为零。
对于商店,在第六轮操作开始有商店,每六轮刷新一次,每次每个商品刷新的概率为 p p p,买东西在一次操作之前,且不费操作。
初始你有 100 T P 0 G , 给你 100TP\,\,0G,给你 100TP0G,给你 n n n和 p p p,求期望的 s p e e d p o i n t s speed\,\,points speedpoints。
Soliution:
首先我们要知道,初始时金币数量为 0 0 0,那么我们每次要在商店买东西前都一定要先进行一次 r a c e race race操作, − 50 T P + 100 G -50TP+100G −50TP+100G,这样才有钱去商店买东西。
然后对于操作,最朴素的就是一次训练一次休息,两回合 + 15 +15 +15分。如果不买东西不需要 r a c e race race操作,现在考虑买东西的情况。
对商店里的商品逐一分析:
1. H o r n & W e i g h t 1.Horn\&Weight 1.Horn&Weight:
H o r n Horn Horn:下次训练分数 × 2 \times 2 ×2,即多 15 15 15分。代价为 100 G 100G 100G,再加上前面的 r a c e race race和后面的 t r a i n train train,即两个操作消耗 100 H P 100HP 100HP获得 30 30 30分,折腾半天不如两次训练来的实在。
W e i g h t : Weight: Weight:下次训练分数 45 45 45且 H p − 100 Hp-100 Hp−100,代价为 200 G 200G 200G,需要两次 r a c e race race才能挣够,即三次操作消耗 200 H P 200HP 200HP加 45 45 45分,甚至不如三次训练。
所以这俩没必要买,纯智商税。
2. 2. 2.两个 L L L的商品:
T P M e d i c i n e ( L ) TP\,\,Medicine(L) TPMedicine(L): + 100 H P +100HP +100HP,代价 100 G 100G 100G,加上前面的 r a c e race race,相当于一次操作 + 50 H P +50HP +50HP,和 r e s t rest rest一样,没必要买来折腾。
M a g i c B o o k ( L ) Magic\,\,Book(L) MagicBook(L): + 15 +15 +15分,代价 100 G 100G 100G,加上前面的 r a c e race race,相当于一次操作 − 50 T P + 15 -50TP+15 −50TP+15分,这不就是 t r a i n train train,买它也没用。
所以这俩可以被相同的操作替代,也没必要买
3. 3. 3.两个 M M M与两个 S S S
T P M e d i c i n e ( S ) TP\,\,Medicine(S) TPMedicine(S): − 25 G + 25 T P -25G+25TP −25G+25TP,游戏里 25 T P 25TP 25TP一点用没有,只有 50 T P 50TP 50TP才有用,所以这玩意得一次买俩才有用,买俩相当于 M M M的体力药。
T P M e d i c i n e ( M ) TP\,\,Medicine(M) TPMedicine(M): − 50 G + 50 T P -50G+50TP −50G+50TP,算上 r a c e race race,相当于花了一次操作白嫖了一次 50 G 50G 50G,这 50 G 50G 50G有没有用还得看后面的魔法书能加多少。
M a g i c B o o k ( S ) Magic\,\,Book(S) MagicBook(S): − 25 G + 3 -25G+3 −25G+3分,观察到上面所有买商品的操作中,没有剩下 25 G 25G 25G的情况,要么剩下 50 G 50G 50G,要么直接有 100 G 100G 100G。所以要是这玩意足够多,肯定买俩或者买四个,如果买一个说明没刷出来更多的。
我们先假设足够多,如果用一次 r a c e race race加四个小书,相当于一次操作 − 50 T P + 12 -50TP+12 −50TP+12分,不如 t r a i n train train。
如果搭配中小体力药,相当于一次操作白 + 6 +6 +6分,当没有体力的时候不亏。
M a g i c B o o k ( M ) Magic\,\,Book(M) MagicBook(M): − 50 G + 7 -50G+7 −50G+7分,同上面,如果用一次 r a c e race race加两个中魔法书,相当于一次操作 − 50 T P + 14 -50TP+14 −50TP+14分,也不如 t r a i n train train。但是搭配中小体力药相当于一次操作白 + 7 +7 +7分,也是没有体力的时候不亏。
分析了这么久,我们发现商店大多数都是智商税,只有在没体力的情况才会对分数有收益,而且如果单拿出来两个回合肯定不如一直训练,没有体力时休息的收益更高。所以策略大体就是:训练,训练,没体力休息,训练,休息,训练 . . . ... ...。
所以当 2 ∣ n 2\mid n 2∣n,或商店没刷新,我们直接输出答案 ( ⌊ n 2 ⌋ + 1 ) × 15 (\lfloor\frac{n}{2}\rfloor+1)\times 15 (⌊2n⌋+1)×15即可。
当 2 ∤ n 2\nmid n 2∤n,且已经刷新商店,我们发现如果按照这个策略:训练,训练,休息,训练 . . . ... ...。在最后一次操作我们会没体力,这时休息对答案做不出任何贡献,所以考虑利用商店。前面已经分析过没有体力时利用体力药和魔法书可以白嫖分数,所以我们的答案有四种情况: 1. 1. 1.白嫖 7 7 7分, 2. 2. 2.白嫖 6 6 6分, 3. 3. 3.白嫖 3 3 3分, 4. 4. 4.没白嫖到。
分别计算四种情况的概率,乘上白嫖的分数,即为最终的期望。具体计算概率的方法可以看代码。
代码
#include
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
inline void read(ll &x){
ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){s=(s<<3)+(s<<1)+(ch&15);ch=getchar();}
x=s*w;
}
ll n,p,T;
ll qpow(ll x, ll y){
ll re=1LL;
while(y){
if(y&1)(re*=x)%=mod;
(x*=x)%=mod,y>>=1;
}
return re;
}
int main(){
read(T);
while(T--){
read(n),read(p);
if(!n){
puts("0");
continue;
}
if(n<6||n%2==0){
printf("%lld\n",(n/2+1)*15LL%mod);
continue;
}
ll now=n/6;//商店刷新次数
ll pa0=qpow(1LL-p+mod,now);//一个道具一直没有
ll pa1=qpow(1LL-p+mod,now-1)*p%mod*now%mod;//一个道具只出现了一次
ll p1=(1LL-pa0+mod)%mod;//一种道具存在一次及以上
ll p2=((1LL-(pa0+pa1)%mod+mod)%mod+mod)%mod;//一种道具存在两次及以上
ll tp=(1LL-(1LL-p1+mod)*(1LL-p2+mod)%mod+mod)%mod;//有能补50hp的体力药
ll ans1=tp*p1%mod;//有+50hp,有+7points
ll ans2=tp*pa0%mod*p2%mod;//有+50hp,无+7points,有两个+3points
ll ans3=tp*pa0%mod*pa1%mod;//有+50hp,无+7points,有一个+3points
printf("%lld\n",(((((n/2+1)*15LL%mod+7*ans1%mod)%mod+6*ans2%mod)%mod+3*ans3%mod)%mod)%mod);
}
}