1. 程式人生 > >UVa 10288 Coupous (條件概率)

UVa 10288 Coupous (條件概率)

urn nat assert char opera viso 分數類 divisor 次數

題目

題目大意

大街上到處在賣彩票, 一元錢一張。購買撕開它上面的錫箔, 你會看到一個漂亮的圖案。圖案有\(n\)種, 如果你收集到所有\(n\)(\(n ≤ 33\))種彩票, 就可以得到大獎。請問, 在平均情況下, 需要買多少張彩票才能得到大獎呢? 如\(n = 5\)時的答案為\(11\frac{5}{12}\)

題解

設已經有\(k\)個圖案: 平均拿\(\frac{n}{n - k}\)次就可多搜集一個, 所以總次數為:
\[n\sum_{i = 0}^{n - 1}\frac{1}{n - i}\]

然後再用個分數類就可以了。

此處再說一個奇妙的事情, 我如果用自己寫的GreatestCommonDivisor

函數會\(WA\), 但是如果用\(C++\)函數庫裏的__gcd就能\(AC\), 至今不能理解。

還有輸出最好不要重載輸出流<<運算符, 容易\(RE\)

另外此題可打表。

代碼

#include <bits/stdc++.h>
using namespace std;
struct Fraction {
  long long numerator, denominator;
  Fraction(register long long knum = 0, register long long kden = 1) {
    if (kden < 0) {
        knum = -knum;
        kden = -kden;
    }
    assert(kden != 0);
    register long long g(__gcd((long long)abs(knum), kden));
    this->numerator = knum / g;
    this->denominator = kden / g;
  }
  inline Fraction operator +(const Fraction& o) const {
      return Fraction(numerator * o.denominator + denominator * o.numerator, denominator * o.denominator);
  }
  inline Fraction operator -(const Fraction& o) const {
      return Fraction(numerator * o.denominator - denominator * o.numerator, denominator * o.denominator);
  }
  inline Fraction operator *(const Fraction& o) const {
      return Fraction(numerator * o.numerator, denominator * o.denominator);
  }
  inline Fraction operator /(const Fraction& o) const {
      return Fraction(numerator * o.denominator, denominator * o.numerator);
  }
  bool operator <(const Fraction& o) const {
      return numerator * o.denominator < denominator * o.numerator;
  }
  bool operator ==(const Fraction& o) const {
      return numerator * o.denominator == denominator * o.numerator;
  }
};
int main(int argc, char const *argv[]) {
  register long long n, k, ans, cases(0);
  while (~scanf("%lld", &n)) {
    register Fraction ans;
    for (register int i(1); i <= n; ++i) {
        ans = ans + Fraction(n, i);
    }
    register long long t(ans.numerator / ans.denominator);
    ans.numerator -= t * ans.denominator;
    if (!ans.numerator) {
      printf("%lld\n", t);
    } else {
      register string s;
      register stringstream ss1, ss2;
      ss1 << t;
      ss1 >> s;
      register int space(s.size());
      for (register int i(0); i <= space; ++i) putchar(' ');
      printf("%lld\n", ans.numerator);
      ss2 << ans.denominator;
      ss2 >> s;
      register int line(s.size());
      printf("%lld ", t);
      for (register int i(0); i < line; ++i) putchar('-');
      putchar('\n');
      for (register int i(0); i <= space; ++i) putchar(' ');
      printf("%lld\n", ans.denominator);
    }
  }
  return 0;
}

UVa 10288 Coupous (條件概率)