首页 > 其他 > 详细

CF464D World of Darkraft - 2

时间:2021-04-09 00:08:57      阅读:27      评论:0      收藏:0      [点我收藏+]

首先明确一点,所有装备的期望相同,只需求出任意一种后答案乘 \(k\) 即可。

\(dp[i][j]\) 表示还需要打 \(i\) 只怪,装备等级为 \(j\) 的金币数量期望。

那么有三种情况:

1.得到的并不是当前类型装备,概率为 \(\frac{k-1}{k}\),这种情况下你一分钱也得不到。

2.得到当前装备的 \(j+1\) 级,概率为 \(\frac{1}{k} \times \frac{1}{j+1}\),然后你可以得到 \(j\) 元。

3.得到当前装备的 $[1,j] $ 级 ,概率为 $\frac{1}{k} \times\frac{j}{j+1} $。

此时金币的期望为 \(\sum_{i=1}^{j} i \times\frac{1}{j}=\frac{\frac{j \times (j+1)}{2}}{j}=\frac{j+1}{2}\)

用滚动数组优化一下,这样可以 \(n^2\) 转移。

但是 \(n \le 10^5\) , 我们得优化一下。

我们要相信 \(\mathrm{Roma}\) 跟我一样非,装备等级不会太高。

理性计算一下:

由上面分析可得,装备由 \(j\) 级 到 \(j+1\) 级的概率为 \(\frac{1}{k \times(j+1)}\) ,那么期望次数为 \(k \times(j+1)\)

记期望最高等级为 \(l\),那么 \(2k+3k+...+lk \le n\)

解得:

\[l < \sqrt{\frac{2(n+1)}{k}} \]

理论上开 \(500\) 即可,但这样有 \(0.0000002\) 的误差,开 \(525\) 即可。

#include <cstdio>

const int MAXN = 525;
int n , k;
double dp[ 2 ][ MAXN + 5 ];

int main( ) {
    scanf("%d %d",&n,&k);
    
    for( int i = 1 ; i <= n ; i ++ )
        for( int j = 1 ; j <= MAXN ; j ++ )
            dp[ i & 1 ][ j ] = ( dp[ ( i - 1 ) & 1 ][ j ] * ( ( k - 1 ) * 1.0 / k ) + ( dp[ ( i - 1 ) & 1 ][ j + 1 ] + j ) * ( 1.0 / ( k * ( j + 1 ) ) ) + ( dp[ ( i - 1 ) & 1 ][ j ] + ( 1 + j ) / 2.0 ) * ( j * 1.0 / ( k * ( j + 1 ) ) ) );
    
    printf("%.10f\n", dp[ n & 1 ][ 1 ] * k );
    return 0;
}

CF464D World of Darkraft - 2

原文:https://www.cnblogs.com/chihik/p/CF464D.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!