大题题意:
一共有n 种不同的优惠券,每次得到每种优惠券的概率相同。问期望多少次可以得到所有n 种的优惠券,以带分数的形式输出!
思路:
这个题 用dp思想比较好理解一些!
令dp[i]表示已经得到了 i种优惠券!
那么dp[i]的转移可以来自i-1种的情况得到一种新的种类!
也可以来自i种 得到了一种原来的种类!
在+1即可!
即:
dp[i] = dp[i-1] * (n-i+1)/n + dp[i] * (i-1)/n + 1;
有一个小规律,即加1的前面系数的和一定是1。
这种套路比较常见了,在一些概率dp中!
详细见代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){
return !b ? a : gcd(b,a%b);
}
struct Fra{
ll fz;
ll fm;
Fra(){fz = fm = 1;}
Fra(ll fz,ll fm):fz(fz),fm(fm){}
Fra operator + (Fra o) {
Fra ans = Fra();
ll t1 = fz*o.fm+fm*o.fz;
ll t2 = fm*o.fm;
ll g = gcd(t1,t2);
t1/=g; t2/=g;
ans.fz = t1;
ans.fm = t2;
return ans;
}
}dp[40];
int bit(ll n){
int a = 0;
while(n){
n/=10;
a++;
}
return a;
}
int main(){
int n;
dp[0].fz = 0;
dp[0].fm = 1;
while(~scanf("%d",&n)){
for (int i = 1; i <= n; ++i){
Fra tmp = Fra((ll)n,(ll)n-i+1);
dp[i] = dp[i-1] + tmp;
}
ll fz = dp[n].fz;
ll fm = dp[n].fm;
if (fz % fm == 0){
printf("%lld\n",fz/fm);
}
else {
ll z = fz/fm;
fz %= fm;
ll g = gcd(fz,fm);
fz /= g; fm/=g;
int bz = bit(z)+1;
for (int i = 0; i < bz; ++i)printf(" ");
printf("%lld\n",fz);
printf("%lld ",z);
int Max = max(bit(fz),bit(fm));
for (int i = 0; i < Max; ++i)printf("-");
puts("");
for (int i = 0; i < bz; ++i)printf(" ");
printf("%lld\n",fm);
}
}
return 0;
}