百事世界杯之旅
题目描述
“……在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字。只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽奖活动,获得球星背包,随声听,更克赴日韩观看世界杯。还不赶快行动!”
你关上电视,心想:假设有n个不同的球星名字,每个名字出现的概率相同,平均需要买几瓶饮料才能凑齐所有的名字呢?
输入输出格式
输入格式:
整数n(2≤n≤33),表示不同球星名字的个数。
输出格式:
输出凑齐所有的名字平均需要买的饮料瓶数。如果是一个整数,则直接输出,否则应该直接按照分数格式输出,例如五又二十分之三应该输出为(复制到记事本):$5 frac{3}{20}$第一行是分数部分的分子,第二行首先是整数部分,然后是由减号组成的分数线,第三行是分母。减号的个数应等于分母的为数。分子和分母的首位都与第一个减号对齐。
分数必须是不可约的。
输入输出样例
输出样例#1:
3
分析:
很明显的数学期望。
首先我们设当前还需要收集$k$个球星,现在的装态为$f(n,k)$,那么转移的方程就是:$f(n,k)=frac {(n-k)*f(n,k)}{n}+frac {k*f(n,k-1)}{n}+1$,因为很明显我们收集到了$n-k$个球星,那么抽到没收集到的球星的概率为$frac {k}{n}$,抽到收集到的球星的概率为$frac {n-k}{n}$,后面的那个+1就是代表多买了一瓶饮料。然后把方程移项,得到:$f(n,k)=f(n,k-1)+frac {n}{k}$。然后注意输出就行了。
Code:
//It is made by HolseLee on 25th July 2018 //Luogu.org P1291 #include<bits/stdc++.h> using namespace std; typedef long long ll; ll n,ans,m=1,ka; inline ll gcd(ll x,ll y) { return y==0?x:gcd(y,x%y); } inline ll get(ll x) { ll ret=0; while(x){ ret++;x/=10; } return ret; } int main() { ios::sync_with_stdio(false); cin>>n; for(int i=n;i>=1;i--){ ans=ans*i+m*n; m*=i;ka=gcd(ans,m); ans/=ka;m/=ka; } ka=ans/m; ans%=m; if(ans==0) printf("%lld ",ka); else { ll gi=get(ka),lu=get(m); for(int i=1;i<=gi;i++) printf(" "); printf("%lld ",ans); if(ka>0) printf("%lld",ka); for(int i=1;i<=lu;i++) printf("-"); printf(" "); for(int i=1;i<=gi;i++) printf(" "); printf("%lld ",m); } return 0; }