首先明确一点,所有装备的期望相同,只需求出任意一种后答案乘 \(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\)
解得:
理论上开 \(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;
}
原文:https://www.cnblogs.com/chihik/p/CF464D.html