Bowcraft
——杭电第二场多校1009-Bowcraft
题意
:
有一把弓,初始等级为
0
0
0 ,商店提供一本升级书,在使用这本升级书时,有
a
A
\frac{a}{A}
Aa 的概率将弓提升
1
1
1 级,如果升级失败,就有
b
B
\frac{b}{B}
Bb 的概率(前提是使用了这本书并且升级失败)使这把弓的等级降为
0
0
0 ,当你从商店购买一本升级书时,商店系统会在
[
0
,
A
−
1
]
[0,A-1]
[0,A−1] 中生成一个随机数
a
a
a ,在
[
0
,
B
−
1
]
[0,B-1]
[0,B−1] 中生成一个随机数
b
b
b ,在购买了升级书后,你需要确定是否使用这本书,问:当你使用最佳策略时,将弓从
0
0
0 级升到
K
K
K 级所需要购买的升级书数量的数学期望是多少。
T T T 组数据,每次输入一组 K , A , B K,A,B K,A,B 其中 ( T ≤ 10 , 1 ≤ K ≤ 1000 , 2 ≤ A , B ≤ 100 ) (T\le 10,1\le K \le 1000,2\le A,B \le 100) (T≤10,1≤K≤1000,2≤A,B≤100)
做法:
考虑使用 d p dp dp 解决该问题, d p [ i ] dp[i] dp[i] 表示将弓从 0 0 0 级升到 K K K 级所需要购买升级书数量的数学期望,为了方便表达,我们令 α = a A \alpha=\frac{a}{A} α=Aa ,令 β = b B \beta=\frac{b}{B} β=Bb .
假设当前的等级为 i i i ,买了一本随机数为 ( a , b ) (a,b) (a,b) 的升级书,我们对这本书有两种处理方法:
1 如果我们选择使用这本书升级,那么将弓升到 i + 1 i+1 i+1 级的期望是 d p [ i ] + 1 + ( 1 − α ) β ⋅ d p [ i + 1 ] + ( 1 − α ) ( 1 − β ) ⋅ ( d p [ i + 1 ] − d p [ i ] ) dp[i]+1+(1-\alpha) \beta \cdot dp[i+1]+(1-\alpha)(1-\beta) \cdot (dp[i+1]-dp[i]) dp[i]+1+(1−α)β⋅dp[i+1]+(1−α)(1−β)⋅(dp[i+1]−dp[i]) ,我们先来解释一下这个式子:
d p [ i ] + 1 dp[i]+1 dp[i]+1 :因为我们确定要使用这本书,所以将弓升到 i + 1 i+1 i+1 的期望一定会先在 d p [ i ] dp[i] dp[i] 的基础上加 1 1 1 ,然后,
( 1 − α ) β ⋅ d p [ i + 1 ] (1-\alpha) \beta \cdot dp[i+1] (1−α)β⋅dp[i+1] :这里 ( 1 − α ) β (1-\alpha) \beta (1−α)β 为升级失败并触发等级降为 0 0 0 情况的概率,当发生这种情况时,需要重新将弓升级到 i + 1 i+1 i+1 级才能满足要求,故这里需要乘 d p [ i + 1 ] dp[i+1] dp[i+1] ,也就是乘以将弓升级到 i + 1 i+1 i+1 级的期望。
( 1 − α ) ( 1 − β ) ⋅ ( d p [ i + 1 ] − d p [ i ] ) (1-\alpha)(1-\beta) \cdot (dp[i+1]-dp[i]) (1−α)(1−β)⋅(dp[i+1]−dp[i]) :这里前面 ( 1 − α ) ( 1 − β ) (1-\alpha)(1-\beta) (1−α)(1−β) 是指弓升级失败但没有触发等级降为零事件的概率,发生这种事件的次数为升级到 i + 1 i+1 i+1 级所需次数与升级到 i i i 级所需次数之差,即使用了升级书但弓的等级不变的次数。
2 如果我们选择不使用这本书升级,那么将弓升到 i + 1 i+1 i+1 级的期望是 d p [ i + 1 ] + 1 dp[i+1]+1 dp[i+1]+1 ,意思是如果不使用这本书,升级到 i + 1 i+1 i+1 的期望依旧要加 1 1 1 。
因此我们可以得到如下的
d
p
dp
dp 方程:
d
p
[
i
+
1
]
=
1
A
B
∑
a
,
b
m
i
n
{
d
p
[
i
+
1
]
+
1
,
d
p
[
i
]
+
1
+
(
1
−
α
)
β
⋅
d
p
[
i
+
1
]
+
(
1
−
α
)
(
1
−
β
)
⋅
(
d
p
[
i
+
1
]
−
d
p
[
i
]
)
}
dp[i+1]= \frac{1}{AB} \sum_{a,b} min \left \{ dp[i+1]+1, dp[i]+1+(1-\alpha) \beta \cdot dp[i+1]+(1-\alpha)(1-\beta) \cdot (dp[i+1]-dp[i])\right \}
dp[i+1]=AB1∑a,bmin{dp[i+1]+1,dp[i]+1+(1−α)β⋅dp[i+1]+(1−α)(1−β)⋅(dp[i+1]−dp[i])}
取 m i n min min 的含义是,对本书进行判断,若使用当前这本书的期望大于不使用当前这本书的期望,则不使用。
对于当前的等级 i i i 和一本书 ( a , b ) (a, b) (a,b) ,如果要使用这本书,那么升到 i + 1 i + 1 i+1 级,不使用的期望 ≥ \ge ≥ 使用的期望
即 d p [ i + 1 ] + 1 ≥ d p [ i ] + 1 + ( 1 − α ) β ⋅ d p [ i + 1 ] + ( 1 − α ) ( 1 − β ) ⋅ ( d p [ i + 1 ] − d p [ i ] ) dp[i+1]+1 \ge dp[i]+1+(1-\alpha) \beta \cdot dp[i+1]+(1-\alpha)(1-\beta) \cdot (dp[i+1]-dp[i]) dp[i+1]+1≥dp[i]+1+(1−α)β⋅dp[i+1]+(1−α)(1−β)⋅(dp[i+1]−dp[i])
化简为: d p [ i + 1 ] ≥ d p [ i ] ⋅ α + β − α β α dp[i+1] \ge dp[i] \cdot \frac{\alpha + \beta -\alpha \beta}{\alpha} dp[i+1]≥dp[i]⋅αα+β−αβ
从上式可见, α + β − α β α \frac{\alpha + \beta -\alpha \beta}{\alpha} αα+β−αβ 值较小的升级书更容易被使用,即 β ( 1 − α ) α \frac{\beta (1-\alpha)}{\alpha} αβ(1−α) 值更小的升级书更容易被使用,因此我们可以先对 A ∗ B A*B A∗B 本书的 β ( 1 − α ) α \frac{\beta (1-\alpha)}{\alpha} αβ(1−α) 值进行排序预处理,假设有 t t t 本书符合使用条件,我们就使用 β ( 1 − α ) α \frac{\beta (1-\alpha)}{\alpha} αβ(1−α) 值前 t t t 小的书,其他的书不使用,那么有:
A B ⋅ d p [ i + 1 ] = ( A B − t ) ⋅ ( d p [ i + 1 ] + 1 ) + ∑ a , b ∈ ( 前 t 小 ) d p [ i ] + 1 + ( 1 − α ) β ⋅ d p [ i + 1 ] + ( 1 − α ) ( 1 − β ) ⋅ ( d p [ i + 1 ] − d p [ i ] ) AB\cdot dp[i+1]=(AB-t)\cdot (dp[i+1]+1)+\sum_{a,b\in (前t小)}dp[i]+1+(1-\alpha) \beta \cdot dp[i+1]+(1-\alpha)(1-\beta) \cdot (dp[i+1]-dp[i]) AB⋅dp[i+1]=(AB−t)⋅(dp[i+1]+1)+∑a,b∈(前t小)dp[i]+1+(1−α)β⋅dp[i+1]+(1−α)(1−β)⋅(dp[i+1]−dp[i])
化简得 d p [ i + 1 ] = A B + d p [ i ] ⋅ ∑ a , b ∈ ( 前 t 小 ) α + β − α β t − ∑ a , b ∈ ( 前 t 小 ) 1 − α dp[i+1]=\frac{AB+dp[i] \cdot \sum_{a,b\in (前t小)} \alpha + \beta -\alpha \beta}{t-\sum_{a,b\in (前t小)}1- \alpha } dp[i+1]=t−∑a,b∈(前t小)1−αAB+dp[i]⋅∑a,b∈(前t小)α+β−αβ
计算:
将符合条件的升级书 ( a , b ) (a,b) (a,b) 按 β ( 1 − α ) α \frac{\beta (1-\alpha)}{\alpha} αβ(1−α) 值从小到大求和,用 s u m 1 sum1 sum1 求和符合条件的 α + β − α β \alpha + \beta -\alpha \beta α+β−αβ ,即 s u m 1 = ∑ i ∈ t α i + β i − α i β i sum1=\sum_{i\in t} \alpha_i + \beta_i -\alpha_i \beta_i sum1=∑i∈tαi+βi−αiβi ,用 s u m 2 sum2 sum2 求和符合条件的 1 − α 1-\alpha 1−α ,即 s u m 2 = ∑ i ∈ t α i sum2=\sum_{i\in t} \alpha_i sum2=∑i∈tαi 。遍历排好序后的 ( α , β ) (\alpha,\beta) (α,β) 对每个 i i i 进行一次判断,判断加上这一对 ( α , β ) (\alpha,\beta) (α,β) 后 d p [ i + 1 ] dp[i+1] dp[i+1] 的预计期望是否变小,若不变小则退出循环,更新 d p [ i + 1 ] dp[i+1] dp[i+1] 的最小值,按照同样的方法递推得到并输出 d p [ K ] dp[K] dp[K]
由于每次递推得到 d p [ i + 1 ] dp[i+1] dp[i+1] 的复杂度为 O ( A B ) O(AB) O(AB) ,总复杂度为 O ( K A B ) O(KAB) O(KAB).
代码:
#include<bits/stdc++.h>
#define ll long long
#define endl "\n"
#define f first
#define s second
using namespace std;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
int t;cin>>t;
while(t--)
{
int k,a1,b1;
cin>>k>>a1>>b1;
double a=a1,b=b1;
vector<double> dp(k+1);
dp[0]=0;//弓箭初始为0级,期望为0
vector<pair<double,double> > ab;
for(int i=1;i<a1;i++)
{
for(int j=0;j<b1;j++)
{
ab.emplace_back((double)i/a,(double)j/b);//预处理求出a/A 与 b/B
}
}
auto cmp = [&](pair<double,double> aa1,pair<double,double> bb1)//从小到大排序
{
double af1=aa1.f,bt1=aa1.s;
double af2=bb1.f,bt2=bb1.s;
return bt1*(1.0-af1)/af1<bt2*(1.0-af2)/af2;
};
sort(ab.begin(),ab.end(),cmp);
for(int i=0;i<k;i++)//k次递推得到dp[K]
{
double tt=0,s1=0,s2=0;
double ab1=a*b;
for(int j=0;j<ab.size();j++)
{
double af=ab[j].f;
double bt=ab[j].s;
double t1=s1+af+bt-af*bt;
double t2=s2+1-af;
if((ab1+dp[i]*t1)/(tt+1-t2)<=(ab1+dp[i]*s1)/(tt-s2))
{
s1=t1;
s2=t2;
tt+=1;
}
}
dp[i+1]=(ab1+dp[i]*s1)/(tt-s2);
}
cout<<fixed<<setprecision(3)<<dp[k]<<endl;//注意保留三位小数
}
return 0;
}