• CF464D World of Darkraft


    题目链接

    又一次跌在了概率期望的坑上。

    显然所有物品一样,可以算出一个的期望后乘以 (k)

    我一开始像的是设 (f(i)) 表示选择一个物品 (i) 次的期望收益,(g(i)(j)) 表示当前已经选择了 (i) 次,装备等级为 (j) 的收益期望,然后写了一堆式子最后优化到了 (O(n)),然后对着样例调了三个小时...结果晚上睡觉的时候突然想到转移的时候的那个收益还要乘上到达该状态的概率,然后就全挂了。

    正解:

    根据绿豆蛙的归宿,倒着转移概率为1,无需记录概率。设 (f(i)(j)) 表示还有 (i) 次选择机会,当前此物品的等级为 (j),从这个状态到最后的期望收益。于是当前有三种后续转移:没选择到此物品;选择到此物品但是爆出的装备等级 (le j);选择到此物品并且爆出 (j+1) 级。于是有:

    [egin{aligned} f_{i,j}&gets-(frac{k-1}{k})--f_{i-1,j}\ &gets-(frac{1}{k(j+1)})-- f_{i-1,j}+t,tle j\ &gets-(frac{1}{k(j+1)})--f_{i-1,j+1}+j end{aligned}]

    于是就可以 (n^2) 转移了。

    但是 (n le 10^5),复杂度无法接受。不过得到等级较大的装备的概率不大,期望得到的等级大概是 (sqrt {n/k}) 级别的。想要得到等级为 (j) 的装备的期望次数是 (2k+3k+4k+...+jk = O(j^2k))。于是只保留前几百级的期望即可。可能需要滚动数组。

    关键代码:

    int nw = 1;
    for (int i = 1; i <= n; ++i, nw ^= 1) {
    	for (int j = 1; j <= up; ++j) {
    		double tmp = f[nw^1][j], ttmp = f[nw^1][j+1];
    		f[nw][j] = tmp*(k-1.0)/k + 1.0/k * (1.0/(j+1.0)*ttmp + j/(1.0+j) + j/(1.0+j)*tmp + j/2.0);
    	}
    }
    printf("%.10lf
    ", f[nw^1][1] * k);
    
  • 相关阅读:
    37 什么时候使用内部临时表
    2 Hadoop集群安装部署准备
    36 为什么临时表可以重名
    maven内置属性
    ProGuard 最全混淆规则说明
    stylus的用法
    vscode 插件 配置
    关于overflow:hidden
    vue-devtools/安装vue-devtools
    对Java中使用两个大括号进行初始化的理解
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13679167.html
Copyright © 2020-2023  润新知