题意:大街上到处在卖彩票,一元钱一张。购买撕开它上面的锡箔,你会看到一个漂亮的图
案。图案有n种,如果你收集到所有n(n≤33)种彩票,就可以得大奖。请问,在平均情况
下,需要买多少张彩票才能得到大奖呢?如n=5时答案为137/12。
分析:设f[i]代表还有i个优惠券没有收集到的期望开箱次数,那么我们只要计算再没有取到的期望+上一个取到的期望+操作次数1,即f[i]=(n-i)/n*f[i]+i/n*f[i+1]+1,移项后是f[i] = f[i+1] + n/i,然后就是一个分数计算的模板了
整理了一个分数类模板,支持常见操作,记录一下:
const int maxn = 510;
typedef long long LL;
struct Fraction{
LL a, b; //a代表分子,b代表分母
Fraction(){
a = 0; b = 1;
}
void reduction(){
if(a == 0){
b = 1;
return;
}
LL gcdnum = __gcd(a, b);
a /= gcdnum;
b /= gcdnum;
}
Fraction(LL num){ //整数
a = num; b = 1;
}
Fraction(LL x, LL y){
a = x, b = y;
this->reduction();
}
void operator = (const LL &num){
a = num; b = 1;
this -> reduction();
}
void operator = (const Fraction &y){
a = y.a; b = y.b;
this -> reduction();
}
Fraction operator + (const Fraction &y) const{
LL gcdnum = __gcd(b, y.b);
Fraction tmp = Fraction(a * (y.b / gcdnum) + y.a * (b / gcdnum) , b / gcdnum * y.b);
tmp.reduction();
return tmp;
}
Fraction operator + (const LL &y) const{
return ((*this) + Fraction(y));
}
Fraction operator - (const Fraction &y) const{
return ((*this) + Fraction(-y.a, y.b));
}
Fraction operator - (const LL &y) const{
return ((*this) - Fraction(y));
}
Fraction operator * (const Fraction &y) const{
Fraction tmp = Fraction(a * y.a, b * y.b);
tmp.reduction();
return tmp;
}
Fraction operator / (const Fraction &y) const{
return ((*this) * Fraction(y.b, y.a));
}
void print(){
if(b == 1){
printf("%lld\n", a);
}
else{
LL num = a / b;
LL tmp = num;
int len = 0;
while(tmp){
len++; tmp /= 10;
}
for(int i = 0; i < len; i++){
printf(" ");
}
if(len != 0) printf(" ");
printf("%lld\n", a % b);
if(num != 0) printf("%lld ", num);
tmp = b;
while(tmp){
printf("-");
tmp /= 10;
}
printf("\n");
for(int i = 0; i < len; i++) printf(" ");
if(len != 0) printf(" ");
printf("%lld\n", b);
}
}
};
本题完整代码:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 510;
typedef long long LL;
struct Fraction{
LL a, b; //a代表分子,b代表分母
Fraction(){
a = 0; b = 1;
}
void reduction(){
if(a == 0){
b = 1;
return;
}
LL gcdnum = __gcd(a, b);
a /= gcdnum;
b /= gcdnum;
}
Fraction(LL num){ //整数
a = num; b = 1;
}
Fraction(LL x, LL y){
a = x, b = y;
this->reduction();
}
void operator = (const LL &num){
a = num; b = 1;
this -> reduction();
}
void operator = (const Fraction &y){
a = y.a; b = y.b;
this -> reduction();
}
Fraction operator + (const Fraction &y) const{
LL gcdnum = __gcd(b, y.b);
Fraction tmp = Fraction(a * (y.b / gcdnum) + y.a * (b / gcdnum) , b / gcdnum * y.b);
tmp.reduction();
return tmp;
}
Fraction operator + (const LL &y) const{
return ((*this) + Fraction(y));
}
Fraction operator - (const Fraction &y) const{
return ((*this) + Fraction(-y.a, y.b));
}
Fraction operator - (const LL &y) const{
return ((*this) - Fraction(y));
}
Fraction operator * (const Fraction &y) const{
Fraction tmp = Fraction(a * y.a, b * y.b);
tmp.reduction();
return tmp;
}
Fraction operator / (const Fraction &y) const{
return ((*this) * Fraction(y.b, y.a));
}
void print(){
if(b == 1){
printf("%lld\n", a);
}
else{
LL num = a / b;
LL tmp = num;
int len = 0;
while(tmp){
len++; tmp /= 10;
}
for(int i = 0; i < len; i++){
printf(" ");
}
if(len != 0) printf(" ");
printf("%lld\n", a % b);
if(num != 0) printf("%lld ", num);
tmp = b;
while(tmp){
printf("-");
tmp /= 10;
}
printf("\n");
for(int i = 0; i < len; i++) printf(" ");
if(len != 0) printf(" ");
printf("%lld\n", b);
}
}
} dp[maxn];
int main()
{
int n;
while(scanf("%d", &n) != EOF)
{
dp[0] = 0;
for(int i = 1; i <= n; i++) dp[i] = dp[i - 1] + Fraction(1, i);
dp[n] = dp[n] * n;
dp[n].print();
}
return 0;
}