牛客模拟赛5【普及组】T4 飞行棋【期望DP】【前缀和】

本题很难!!!所以单独拎出来讲


显然要棋子在 [ 1 , d ) [1,d) [1,d) [ d , n ] [d,n] [d,n] 的时候分开做。
当棋子在 [ 1 , d ) [1,d) [1,d) 的时候,假设现在在位置 p p p,骰子扔到的是 x x x 点,那么棋子可能会变到 p − x p−x px x − p x−p xp 的位置
发现只有 x x x 恰好等于 p p p 的时候才可以结束,否则 p p p 将变为依然在 [ 1 , d ) [1,d) [1,d) 中的另一个位置 p p p′。那么其实等价于 1 ∼ d − 1 1∼d−1 1d1 中一直随机一个数,直到随机到 1 1 1 时停止,求期望次数
设期望 s s s 次扔到点 1 1 1,那么有

s = d − 2 d − 1 ( s + 1 ) + 1 d − 1 s=\frac{d-2}{d-1}(s+1)+\frac{1}{d-1} s=d1d2(s+1)+d11
解方程得到 s = d − 1 s=d−1 s=d1
那么当棋子在 [ 1 , d ) [1,d) [1,d) 时,期望 d − 1 d−1 d1 次才会回到点 0
那么当棋子所在位置 p ≥ d p≥d pd 时,由于只会不停往左走,所以可以 f [ i ] f[i] f[i] 表示点 i i i 开始期望多少次可以回到点 0 0 0,这样是没有后效性的
得到DP转移方程:

f [ i ] = ( ∑ j = i − d + 1 i − 1 f [ j ] + 1 ) + f [ i − d ] d f[i] = (\sum_{j=i-d+1}^{i-1}{f[j]+1})+\frac{f[i-d]}{d} f[i]=(j=id+1i1f[j]+1)+df[id]
前缀和优化求和即可
时间复杂度 O ( T n ) O(Tn) O(Tn)

以上的部分解释载自zycdalao的博客

代码

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
double sum[1000010],f[1000010];
int T,n,d;
int main()
{
    cin>>T;
    while(T--)
     {
     	scanf("%d%d",&n,&d);
     	f[0]=sum[0]=1;
     	for(int i=1; i<d; i++)
     	   f[i]=d-1,sum[i]=sum[i-1]+f[i];
     	for(int i=d; i<=n; i++)
     	 {
     	 	f[i]=(sum[i-1]-sum[i-d]+d-1)/d+f[i-d]/d; //前缀和优化
     	 	sum[i]=sum[i-1]+f[i];
		 }
		printf("%.2lf\n",f[n]);
	 }
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值