现在的位置: 首页 > 综合 > 正文

UVa Problem Solution: 10254 – The Priest Mathematician

2013年08月03日 ⁄ 综合 ⁄ 共 2422字 ⁄ 字号 评论关闭

From the description of this problem we can easily draw the recurrence of
   f(n) = 2*f(n-k) + 2^k - 1
and the base cases of
   f(0) = 0 and f(1) = 1
However, how can we determine which k would give the minimum value of f(n)?
Suppose k is giving the minimum value, then it must satisfy
   2*f(n-k) + 2^k - 1 <= 2*f(n-(k+1)) + 2^(k+1) - 1,
which can be deduced to
   f(n-k) - f(n-k-1) <= 2^(k-1).
Thus, let d(n) = f(n) - f(n-1), and we can use d(n) to determine the value
 of k through the inequality of
   d(n-k) <= 2^(k-1)
and the fact that d(n) is a non-decreasing sequence.

Code:

  1. /***************************************************************************
  2.  *   Copyright (C) 2008 by Liu Kaipeng                                     *
  3.  *   LiuKaipeng at gmail dot com                                           *
  4.  ***************************************************************************/
  5. /* @JUDGE_ID 00000 10254 C++ "The Priest Mathematician" */
  6. #include <algorithm>
  7. #include <cstdio>
  8. #include <cstring>
  9. #include <deque>
  10. #include <fstream>
  11. #include <iostream>
  12. #include <list>
  13. #include <map>
  14. #include <queue>
  15. #include <set>
  16. #include <stack>
  17. #include <string>
  18. #include <vector>
  19. #include "big_unsigned.hpp"
  20. using namespace std;
  21. /*
  22.  * From the description of this problem we can easily draw the recurrence of
  23.  *   f(n) = 2*f(n-k) + 2^k - 1
  24.  * and the base cases of
  25.  *   f(0) = 0 and f(1) = 1
  26.  * However, how can we determine which k would give the minimum value of f(n)?
  27.  * Suppose k is giving the minimum value, then it must satisfy
  28.  *   2*f(n-k) + 2^k - 1 <= 2*f(n-(k+1)) + 2^(k+1) - 1,
  29.  * which can be deduced to
  30.  *   f(n-k) - f(n-k-1) <= 2^(k-1).
  31.  * Thus, let d(n) = f(n) - f(n-1), and we can use d(n) to determine the value 
  32.  * of k through the inequality of
  33.  *   d(n-k) <= 2^(k-1)
  34.  * and the fact that d(n) is a non-decreasing sequence.
  35.  */
  36. int const size = 10001;     
  37. big_unsigned numbers[size];
  38. big_unsigned pow2[1500];
  39. big_unsigned diff[size];
  40. void gen_numbers()
  41. {
  42.   pow2[0] = 1;
  43.   for (int n = 1; n < 1500; ++n)
  44.     pow2[n] = pow2[n-1] * 2;
  45.   
  46.   numbers[0] = 0, numbers[1] = 1;
  47.   diff[0] = 0, diff[1] = 1;
  48.   int k = 1;
  49.   for (int n = 2; n < size; ++n) {
  50.     if (diff[n-k] > pow2[k-1]) ++k;
  51.     numbers[n] = numbers[n-k] * 2;
  52.     numbers[n] += pow2[k];
  53.     numbers[n] -= 1;
  54.     diff[n] = numbers[n] - numbers[n-1];
  55.   }
  56. }
  57.           
  58. int main(int argc, char *argv[])
  59. {
  60. #ifndef ONLINE_JUDGE
  61.   freopen((string(argv[0]) + ".in").c_str(), "r", stdin);
  62.   freopen((string(argv[0]) + ".out").c_str(), "w", stdout);
  63. #endif
  64.   gen_numbers();
  65.   for (int n; cin >> n; ) cout << numbers[n] << '/n';
  66.   return 0;
  67. }

抱歉!评论已关闭.