题目描述
你关上电视,心想:假设有 (n) 个不同的球星名字,每个名字出现的概率相同,平均需要买几瓶饮料才能凑齐所有的名字呢?
期望dp 水题 (bushi)。但这输出也未免太毒瘤了吧。
设 (f[i]) 表示当前当前有 (i) 个球星的名字的期望。
我们有 (iover n) 的概率抽到的是之前取到的,这时候我们就还需要再抽 (f[i]) 次,所以期望就是 ({iover n} imes (f[i] + 1))
还有 ({n-i}over i) 的概率抽到的是之前没有取到的,这时候我们只需要再取 (f[i-1]) 次就可以,那么期望就是 ({{n-i}over i} imes ({f[i-1] + 1}))
然后我们就得到了递推式 (f[i] = {iover n} imes (f[i] + 1) + {{n-i}over i} imes ({f[i-1] + 1}))
化简一下可以得到: (f[i] = f[i-1] + {nover{n-i}})
转化一下形式变为 (displaystylesum_{i=1}^{n} {nover{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
",ans);
else
{
for(int i = 1; i <= wei(ans); i++) printf(" ");
printf("%lld
",zi);
printf("%lld",ans);
for(int i = 1; i <= wei(mu); i++) printf("-");
printf("
");
for(int i = 1; i <= wei(ans); i++) printf(" ");
printf("%lld
",mu);
}
return 0;
}