洛谷P1291
【题目描述】
“……在2002年6月之前购买的百事任何饮料的瓶盖上都会有一个百事球星的名字。只要凑齐所有百事球星的名字,就可参加百事世界杯之旅的抽奖活动,获得球星背包,随声听,更克赴日韩观看世界杯。还不赶快行动!”
你关上电视,心想:假设有n个不同的球星名字,每个名字出现的概率相同,平均需要买几瓶饮料才能凑齐所有的名字呢?
【输入】
整数n(2≤n≤33),表示不同球星名字的个数。
【输出】
输出凑齐所有的名字平均需要买的饮料瓶数。如果是一个整数,则直接输出,否则应该直接按照分数格式输出,例如五又二十分之三应该输出为(复制到记事本): 5 \frac{3}{20}5203 第一行是分数部分的分子,第二行首先是整数部分,然后是由减号组成的分数线,第三行是分母。减号的个数应等于分母的为数。分子和分母的首位都与第一个减号对齐。
分数必须是不可约的。
【样例输入】
2
【样例输出】
3
分析:
概率与期望模板,dp即可
注意答案输出格式!!坑惨了我!!
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=40;
#define TQX pair<ll,ll>
inline TQX add(ll a,ll b,ll c,ll d){
ll x=a*d+b*c,y=b*d;
ll g=__gcd(x,y);
x=x/g;y=y/g;
return make_pair(x,y);
}
ll n,ans;
TQX f[N];
int main(){
scanf("%lld",&n);
f[0]=make_pair(0,1);
for(int i=1;i<=n;i++)
f[i]=add(f[i-1].first,f[i-1].second,n,n-i+1);
ll zs=f[n].first/f[n].second,fz=f[n].first%f[n].second,fm=f[n].second;
if(fz==0) printf("%lld",zs);
else{
ll t1=zs,len1=0,t2=fm,len2=0;
while(t1){
len1++;
t1=t1/10;
}
while(t2){
len2++;
t2=t2/10;
}
for(int i=1;i<=len1;i++) printf(" ");
printf("%lld\n",fz);
printf("%lld",zs);
for(int i=1;i<=len2;i++) printf("-");
printf("\n");
for(int i=1;i<=len1;i++) printf(" ");
printf("%lld\n",fm);
}
return 0;
}