2023CCPC湘潭邀请赛 F - Timaeus 期望dp

题目链接:https://codeforces.com/gym/104396/problem/F

题意:初始有a朵小花,一次操作可以消耗b朵小花合成1朵大花,同时一次操作可以从两个技能中选择一个,一个是有p%的概率消耗b朵小花合成2朵大花,一个是有q%的概率消耗b朵小花合成1朵大花+1朵小花,问最大期望合成的大花数量是多少

之前没怎么写过期望dp 碰到就寄了 赛时dp转移写的i从大到小 还分类讨论了好几次 苦苦不能过样例2 uu
dp[i]代表有i朵小花时 大花个数的最大期望值
i从1到a进行dp dp[a]为答案

dp[i] = \max \begin{cases} \ p * (dp[i-b] + 2) + (1-p) * (dp[i-b] + 1) \\ \ q * (dp[i+1-b] + 1) + (1-q) * (dp[i-b] + 1) \end{cases}
上面代表选择p的技能 下面代表选择q的技能 转移由题目内容可以推出
需要注意的是i-b和i-b+1数组下标不能为负数
有一个很重要的原因就是 样例为4 2的时候 dp[1]=0 因为只有1朵小花是无法合成的 而我从大到小dp没有考虑这个初始转移情况所以错了

坑点 注意特判:b=1的时候 需要从两个技能中选择其中一个一直进行操作 输出更大的那个答案
选择p的时候 dp[i] = p * (dp[i-b] + 2) + (1-p) * (dp[i-b] + 1);同样遍历到dp[a]为答案
选择q的时候 需要推一个级数求和 或者可以跑循环直到影响小于1e-9为止
我们假设a为1的时候进行q技能操作 那么得到大花数量X可以为1 2 3... n
P(X=1) =(1-q) 说明第一次技能没有实现
P(X=2) =q * (1-q) 说明第一次技能实现 第二次没有实现 一共得到2朵大花
以此类推 P(X=n) =q^(n-1) * (1-q) 前n-1次技能实现 第n次没有实现 一共得到n朵大花
根据期望的定义 可以知道EX=1*P(X=1) + 2*P(X=2) + ... + n*P(X=n) + ...
即EX=(1-q) + 2*q*(1-q) + 3*q^2*(1-q) + ... + n*q^(n-1)*(1-q) + ...
提出公因式(1-q)有 EX/(1-q) = 1 + 2q + 3q^2 + ... + nq^(n-1) + ... 
如果你直接知道右式的值 就可以直接用来计算了 如果不知道的话还是要推一下
我们想办法计算右式的值 可以发现右式是由 S = 1 + q + q^2 + q^3 + ... + q^n + ... 求导得来
S的值可以用等比数列求和 由于n趋向无穷大 0<q<1 所以q^n近似为0 得到S=1/(1-q)
S的值也可以用q*S-S = 1 提出S 得到S=1/(1-q)
两边同时求导可以得到 S' = 1 + 2q + 3q^2 + ... + nq^(n-1) + ... = 1 / (1-q)^2 = EX/(1-q)
再把(1-q)乘回去就可以得到 EX = 1/(1-q)
这是进行一次q操作的期望值 初始有a朵小花就可以进行a次这样的类似操作 所以答案是a/(1-q)
这个值和p操作的dp[a]值取最大输出即可

(等之后学了latex再看看把式子写的好看一点x 先放上来再说

核心代码:

ll a, b;
ld p, q;
ld dp[N];

void solve()
{
	cin >> a >> b >> p >> q;
	p = p / 100, q = q / 100;
	if (b == 1)
	{
		ld ans = 0;
		for (int i = 1; i <= a; i++)
        {
            if (i - b >= 0)dp[i] = p * (dp[i - b] + 2) + (1 - p) * (dp[i - b] + 1);
        }
		ans = dp[a];
		ans = max(ans, a * (1.0 / (1 - q)));
		printf("%.15Lf\n", ans);
		return;
	}
	for (int i = 1; i <= a; i++)
	{
		if (i - b >= 0)dp[i] = max(p * (dp[i - b] + 2) + (1 - p) * (dp[i - b] + 1), q * (dp[i + 1 - b] + 1) + (1 - q) * (dp[i - b] + 1));
		//cout<<i<<" "<<dp[i]<<endl;
	}
	printf("%.15Lf\n", dp[a]);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值