P1291 [SHOI2002]百事世界杯之旅

题目描述

Link

你关上电视,心想:假设有 \(n\) 个不同的球星名字,每个名字出现的概率相同,平均需要买几瓶饮料才能凑齐所有的名字呢?


期望dp 水题 (bushi)。但这输出也未免太毒瘤了吧。

\(f[i]\) 表示当前当前有 \(i\) 个球星的名字的期望。

我们有 \(i\over n\) 的概率抽到的是之前取到的,这时候我们就还需要再抽 \(f[i]\) 次,所以期望就是 \({i\over n}\times (f[i] + 1)\)

还有 \({n-i}\over i\) 的概率抽到的是之前没有取到的,这时候我们只需要再取 \(f[i-1]\) 次就可以,那么期望就是 \({{n-i}\over i} \times ({f[i-1] + 1})\)

然后我们就得到了递推式 \(f[i] = {i\over n}\times (f[i] + 1) + {{n-i}\over i} \times ({f[i-1] + 1})\)

化简一下可以得到: \(f[i] = f[i-1] + {n\over{n-i}}\)

转化一下形式变为 \(\displaystyle\sum_{i=1}^{n} {n\over{n-i}}\)

然后在求的的时候注意通分一下就行。

Code

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define int long long
int n,mu,zi,ans;
int gcd(int a,int b)
{
	if(b == 0) return a;
	else return gcd(b,a%b);
}
int wei(int x)
{
	int res = 0;
	while(x)
	{
		res++;
		x /= 10;
	}
	return res;
}
signed main()
{
	scanf("%lld",&n);
	mu = 1, zi = n;
	for(int i = 2; i <= n; i++)
	{
		zi = zi * i + n * mu;//通分
		mu = mu * i;
		int res = gcd(mu,zi);
		mu /= res;
		zi /= res;
	}
	int ans = zi / mu;//求带数
	zi %= mu;
	if(zi == 0) printf("%lld\n",ans);
	else
	{
		for(int i = 1; i <= wei(ans); i++) printf(" ");
		printf("%lld\n",zi);
		printf("%lld",ans);
		for(int i = 1; i <= wei(mu); i++) printf("-");
		printf("\n");
		for(int i = 1; i <= wei(ans); i++) printf(" ");
		printf("%lld\n",mu);
	}
	return 0;
}
posted @ 2020-10-21 15:15  genshy  阅读(85)  评论(1编辑  收藏  举报