Roll or Increment 题解(at_abc224 G 概率与期望)

Roll or Increment 题解(at_abc224 G 概率与期望)

题目

Roll or Increment 地址:at_abc224_G

解析

  • TAG: 数学,概率和期望

  • DESCRIPITION:
       N N N 面的骰子,求从初始点数 S S S 操作到目标点数 T T T 的期望代价,有两种操作对应两个操作代价。
      op1: 花费代价 A A A另点数加一。
      op2: 花费代价 B B B随机投一个点数。

  • SOLUTION:

    (1)步骤1:分别分析代价
      先分别分析一下只使用一种操作到目标点数的代价,设当前点数为 i i i,我们的目标点数为 T T T

      操作1: 仅仅当 i ≤ T i≤T iT,代价为 ( T − i ) ⋅ A (T-i)·A (Ti)A,可以理解为 i i i 从小到大离 T T T 的距离乘 A A A 就是op1的代价,设置这个距离再加上 T T T 点本身为 L = T − i + 1 L = T - i + 1 L=Ti+1
      所以代价为 ( T − i ) ⋅ A = ( L − 1 ) ⋅ A (T-i)·A = (L-1)·A (Ti)A=(L1)A
      操作2: 由于随机扔骰子全看概率,这里的代价只能求一个平均代价: N ⋅ B N·B NB

    (2)结合起来分析最小代价
      前面我们做了分别分析代价的工作,但实际上我们要做的是一个不断循环迭代分析的工作,所以需要两个操作结合起来看。
      那我们在当前点数 i i i 的基础上时再做操作选择时,就要判断 ( L − 1 ) ⋅ A ≤ N ⋅ B (L-1)·A ≤ N·B (L1)ANB 是否成立,若成立就说明操作1更优先。
      于是,我们得到一个区间 ( T − L , T ] (T-L,T] (TL,T] ,点数在区间内则可以直接循环op1就结束了,区间外则先op2,再根据随机点数位置判断。
      得到最小后续期望
    f ( i ) = { ( L − 1 ) ⋅ A T-L<i≤T, X else. f(i)= \begin{cases} (L-1)·A & \text{T-L<i≤T,}\\ X& \text{else.} \end{cases} f(i)={(L1)AXT-L<i≤T,else.
      其中后续期望 X = B + N − L N ⋅ X + 1 N ⋅ ∑ k = 0 L − 1 k A X = B + \frac{N-L}{N} ·X+\frac{1}{N}· \sum\limits_{k=0}^{L-1}{kA} X=B+NNLX+N1k=0L1kA

    (3)分析区间外时后续期望X与L关系
      解方程得: X = N ⋅ B L + A ⋅ ( L − 1 ) 2 X = \frac{N·B}{L} +\frac{A·(L-1)}{2} X=LNB+2A(L1)
      求导算极值: L = 2 B N A L = \sqrt{\frac{2BN}{A}} L=A2BN ,此时 X X X 最小
    (4)比较一下结合求解后的 X X X与直接利用op1算出来的答案输出最小值即可

参考源码

#include<iostream>
#include<cmath>
#include<iomanip>
using namespace std;
typedef long long ll;
ll N, S, T, A, B;

double X_L(ll L) {
    return A * (L - 1) / 2.0 + B * N * 1.0/ L;
}
int main() {
    cin >> N >> S >> T >> A >> B;

    ll L = sqrt(2.0 * B * N / A);

    double res = 1e18;

    //if (T >= S) res = min(res, A *1.0* (T - S));  // 区间内时期望
    if (T >= S) res = A *1.0* (T - S);  // 区间内时期望
    
    // minx可能不是整数,算一下边缘整数
    for (ll i = L-1; i <= L+1; i++) {
        if (i >= 1 && i <= T) // 边界情况,i=1时相当于不执行方案1一直重扔,i=x时相当于扔到T左边就一直加1
            res = min(res, X_L(i));  // 与区间外内期望比较
    }
    cout<<fixed<<setprecision(8);
    cout << res << endl;
    return 0;
}

代码参考博客https://blog.csdn.net/cmershen/article/details/120930761

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值