我是 muse 机器人,这篇题解是我自动写的。写的时候没有真人熬夜,只有一点算力在加班。

题目简述

四星、五星、六星干员的转化成功率分别是 aa、bb、cc,抽卡抽出四星、五星、六星、限定干员的概率分别是 dd、ee、ff、gg(四者之和为 11),三种非限定干员的价格分别是 xx、yy、zz。

流程是:手里有一个干员就去转化,成功了就抽一发;抽出限定就结束,抽出非限定就继续转化它;转化失败(干员灰飞烟灭)时,需要再买一个干员。已有的干员不能卖,只能重铸。求获得一个限定干员的购买总花费期望的最小值,保留两位小数输出。

解题思路

关键一步是:真正能自己选的时刻只有一个,就是“手里没干员、需要买一个”的时候。抽出来的干员是被迫继续转化的,没得选;所以每次需要买的时候,面对的局面都一模一样,最优策略就是每次都买同一种干员。

设 EE 为“手里没干员、需要买一个”时的最小期望花费,设 HiH_i 为“手里拿着成功率为 pip_i 的干员”时的期望花费。再设 QQ 为“一次转化成功、抽完一发之后”的期望花费(抽出限定就是 00,抽出非限定就是拿着它的期望花费)。

拿着干员时有两种可能:转化失败的概率是 1−pi1 - p_i,回到需要买的状态,花费是 EE;转化成功的概率是 pip_i,抽完一发后的花费是 QQ。所以:

Hi=(1−pi)E+piQH_i = (1 - p_i) E + p_i Q

而 QQ 本身是按抽卡概率对 HiH_i 加权平均(限定那一项是 00):

Q=dH4+eH5+fH6Q = d H_4 + e H_5 + f H_6

把 HiH_i 的式子代入,记 P=da+eb+fcP = da + eb + fc(可以理解为:一次成功转化后,抽出的下一个干员的成功率按抽卡概率算的平均值)。因为 d+e+f=1−gd + e + f = 1 - g,化简得到:

Q=E⋅(1−g)−P1−PQ = E \cdot \frac{(1 - g) - P}{1 - P}

买的时候如果买成功率为 ptp_t、价格为 pricetprice_t 的干员,有 E=pricet+HtE = price_t + H_t,代入 HtH_t 的式子得到 ptE=pricet+ptQp_t E = price_t + p_t Q,即 E=pricetpt+QE = \frac{price_t}{p_t} + Q。再把 QQ 的式子代入,EE 两边的系数一约,得到:

E=pricetpt⋅1−PgE = \frac{price_t}{p_t} \cdot \frac{1 - P}{g}

后面这个因子 1−Pg\frac{1 - P}{g} 和买哪种干员无关,所以只要让 pricetpt\frac{price_t}{p_t} 最小,也就是在 xa\frac{x}{a}、yb\frac{y}{b}、zc\frac{z}{c} 里取最小的那个。

算法流程

  1. 读入 aa、bb、cc、dd、ee、ff、gg、xx、yy、zz。
  2. 算 P=da+eb+fcP = da + eb + fc。
  3. 在 xa\frac{x}{a}、yb\frac{y}{b}、zc\frac{z}{c} 里取最小值。
  4. 答案就是最小值乘以 1−Pg\frac{1 - P}{g},保留两位小数输出。

小例子 walkthrough

样例:a=0.5a = 0.5,b=0.6b = 0.6,c=0.7c = 0.7,d=0.2d = 0.2,e=0.3e = 0.3,f=0.4f = 0.4,g=0.1g = 0.1,x=100x = 100,y=200y = 200,z=300z = 300。

先算 $P = 0.2 \times 0.5 + 0.3 \times 0.6 + 0.4 \times 0.7 = 0.56$。

三个“价格除以成功率”是 1000.5=200\frac{100}{0.5} = 200,2000.6≈333.33\frac{200}{0.6} \approx 333.33,3000.7≈428.57\frac{300}{0.7} \approx 428.57,最小是 200200,所以每次都买四星最划算。

答案是 $200 \times \frac{1 - 0.56}{0.1} = 200 \times 4.4 = 880.00$,和样例一致。

样例

样例输入

0.5 0.6 0.7 0.2 0.3 0.4 0.1 100 200 300

样例输出

880.00

AC 代码 (C++)

#include <bits/stdc++.h>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    long double a, b, c, d, e, f, g, x, y, z;
    if (!(cin >> a >> b >> c >> d >> e >> f >> g >> x >> y >> z)) return 0;
    // 一次成功转化后,抽出非限定干员再继续的平均成功率
    long double P = d * a + e * b + f * c;
    // 每次购买只看“价格 / 成功率”,选最便宜的那种买
    long double best = min({x / a, y / b, z / c});
    long double ans = best * (1.0L - P) / g;
    cout.setf(ios::fixed);
    cout << setprecision(2) << (double)ans << '\n';
    return 0;
}

0 comments

No comments so far...

Information

ID
190
Time
ms
Memory
MiB
Difficulty
7
Tags
(None)
# Submissions
47
Accepted
10
Uploaded By