洛谷P1291 [SHOI2002]百事世界杯之旅 [数学期望]
百事世界杯之旅
题目描述
“……在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字。只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽奖活动,获得球星背包,随声听,更克赴日韩观看世界杯。还不赶快行动!”
你关上电视,心想:假设有n个不同的球星名字,每个名字出现的概率相同,平均需要买几瓶饮料才能凑齐所有的名字呢?
输入输出格式
输入格式:
整数n(2≤n≤33),表示不同球星名字的个数。
输出格式:
输出凑齐所有的名字平均需要买的饮料瓶数。如果是一个整数,则直接输出,否则应该直接按照分数格式输出,例如五又二十分之三应该输出为(复制到记事本):$5 \frac{3}{20}$第一行是分数部分的分子,第二行首先是整数部分,然后是由减号组成的分数线,第三行是分母。减号的个数应等于分母的为数。分子和分母的首位都与第一个减号对齐。
分数必须是不可约的。
输入输出样例
- 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\n",ka);
- else {
- ll gi=get(ka),lu=get(m);
- for(int i=1;i<=gi;i++)
- printf(" ");
- printf("%lld\n",ans);
- if(ka>0)
- printf("%lld",ka);
- for(int i=1;i<=lu;i++)
- printf("-");
- printf("\n");
- for(int i=1;i<=gi;i++)
- printf(" ");
- printf("%lld\n",m);
- }
- return 0;
- }