zzuli oj-2265: collect(期望dp)

2265: collect

时间限制: 1 Sec  内存限制: 256 MB
提交: 21  解决: 9
[ 提交][ 状态][ 讨论版][命题人: admin]

题目描述

“2018年夏天世界杯就要在俄罗斯举办了,作为本次赛事最大的赞助商百事公司推出了隆重的赞助活动,任何球迷只要购买百事可乐都有机会中奖得到一张世界杯的门票。中奖规则是这样的:百事的每一瓶饮料的瓶盖上都会有一个百事球星的名字,并且每一个专买店会印有该店的ID,你只要在s个百事专卖店购买百事饮料,并凑齐所有百事球星的名字且这些瓶盖必须来自s个不同的专卖店,即每个专买店至少贡献一个瓶盖,就可以免费赴俄罗斯观看世界杯。还不赶快行动!......”

现在有n个百事球星的名字,每个名字出现的概率相同,从小明家到学校的路上愉好有s个专买店,小明每天放学回家都会等概率地走进一家专买店并购买一瓶百事饮料,现在小明要你替他算一下他平均要买几瓶百事饮料才能达到中奖要求。

输入

输入仅一行,包含两个数字n和s (0< n , s <= 1 000)

输出

输出一个数,表示小明平均要买几瓶百事饮料才能达到中奖要求,结果保留4位小数

样例输入

1 2

样例输出

3.0000

提示

样例解释:有一个百事球星的名字,有两个专买店,不妨称之为1号店和2号店,小明第一天放学回家时随机走进一家专买店购买了一瓶饮料,我们不妨假设他进的是1号店,则第二天进2号店的概率是1/2,此事件发生则小明就中奖了;如果第二天小明还是进1号店第三天进了2号店,概率是1/4,花了3天才中奖;同理花4天才中奖的概率是1/8,花5天才中奖的概率是1/16,以此类推,小明中奖的平均天数即为1/2*2+1/4*3+1/8*4+1/16*5+......=3

题解:设dp[i][j]为抽到i个有效球星且来自j个商店的期望天数,然后列出转移方程:

dp[i][j]*n*s=i*j*(dp[i][j]+1)+(n-i+1)*(j-1)*(dp[i-1][j]+1)+(n-i+1)*(s-j+1)*(dp[i-1][j-1]+1)+(sj+1)*(i-1)*(dp[i][j-1]+1)即可。

为什么期望dp通常倒着来?

#include<stdio.h>
double dp[1005][1005];
int main(void)
{
	int n,s;
	scanf("%d%d",&n,&s);
	for(int i=n;i>=0;i--)
		for(int j=s;j>=0;j--)
		{
			if(i==n && j==s) dp[i][j]=0;
			else dp[i][j]=(1.0*(n-i)*(s-j)*dp[i+1][j+1]+1.0*(n-i)*(j)*dp[i+1][j]+1.0*(i)*(s-j)*dp[i][j+1]+n*s)/(1.0*(n*s-i*j));
		}
	printf("%.4f\n",dp[0][0]);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值