【POJ1707】【伯努利数】Sum of powers

Description

A young schoolboy would like to calculate the sum

for some fixed natural k and different natural n. He observed that calculating i k for all i (1<=i<=n) and summing up results is a too slow way to do it, because the number of required arithmetical operations increases as n increases. Fortunately, there is another method which takes only a constant number of operations regardless of n. It is possible to show that the sum S k(n) is equal to some polynomial of degree k+1 in the variable n with rational coefficients, i.e.,

We require that integer M be positive and as small as possible. Under this condition the entire set of such numbers (i.e. M, a k+1, a k, ... , a 1, a 0) will be unique for the given k. You have to write a program to find such set of coefficients to help the schoolboy make his calculations quicker.

Input

The input file contains a single integer k (1<=k<=20).

Output

Write integer numbers M, a k+1, a k, ... , a 1, a 0 to the output file in the given order. Numbers should be separated by one space. Remember that you should write the answer with the smallest positive M possible.

Sample Input

2

Sample Output

6 2 3 1 0

Source

【分析】
题意就是给出一个k,找一个最小的M使得 中a[i]皆为整数.
这个涉及到伯努利数的一些公式,如果不知道的话基本没法做..

1. 伯努利数与自然数幂的关系:

2. 伯努利数递推式:


先通过递推式求得伯努利数,然后用1公式并将中间的(n+1) ^ i,变成n ^ i,后面再加上n ^ k,化进去就行了。
 1 /*

 2 宋代朱敦儒

 3 《西江月·世事短如春梦》

 4 世事短如春梦,人情薄似秋云。不须计较苦劳心。万事原来有命。

 5 幸遇三杯酒好,况逢一朵花新。片时欢笑且相亲。明日阴晴未定。 

 6 */

 7 #include <cstdio>

 8 #include <cstring>

 9 #include <algorithm>

10 #include <cmath>

11 #include <queue>

12 #include <vector>

13 #include <iostream>

14 #include <string>

15 #include <ctime>

16 #define LOCAL

17 const int MAXN = 20 + 10;

18 const double Pi = acos(-1.0);

19 using namespace std;

20 typedef long long ll;

21 ll gcd(ll a, ll b){return b == 0? a: gcd(b, a % b);} 

22 struct Num{

23        ll a, b;//分数,b为分母 

24        Num(ll x = 0, ll y = 0) {a = x;b = y;}

25        void update(){

26            ll tmp = gcd(a, b);

27            a /= tmp;

28            b /= tmp;

29        }

30        Num operator + (const Num &c){

31            ll fz = a * c.b + b * c.a, fm = b * c.b;

32            if (fz == 0) return Num(0, 1);

33            ll tmp = gcd(fz, fm);

34            return Num(fz / tmp, fm / tmp);

35        } 

36 }B[MAXN], A[MAXN];

37 ll C[MAXN][MAXN];

38 

39 void init(){

40      //预处理组合数 

41      for (int i = 0; i < MAXN; i++) C[i][0] = C[i][i] = 1;

42      for (int i = 2; i < MAXN; i++)

43      for (int j = 1; j < MAXN; j++) C[i][j] = C[i - 1][j] + C[i - 1][j - 1];

44      //预处理伯努利数 

45      B[0] = Num(1, 1);

46      for (int i = 1; i < MAXN; i++){

47          Num tmp = Num(0, 1), add;

48          for (int j = 0; j < i; j++){

49              add = B[j];

50              add.a *= C[i + 1][j];

51              tmp = tmp + add;

52          }

53          if (tmp.a) tmp.b *= -(i + 1);

54          tmp.update();

55          B[i] = tmp;

56      } 

57 }

58 void work(){

59      int n;

60      scanf("%d", &n);

61      ll M = n + 1, flag = 0, Lcm;

62      A[0] = Num(0, 1);

63      for (int i = 1; i <= n + 1; i++){

64          if (B[n + 1 - i].a == 0) {A[i] = Num(0, 1);continue;}

65          Num tmp = B[n + 1 - i];

66          tmp.a *= C[n + 1][i];//C[n+1][i] = C[n + 1][n + 1 - i]

67          tmp.update();

68          if (flag == 0) Lcm = flag = tmp.b;

69          A[i] = tmp;

70      }

71      A[n] = A[n] + Num(n + 1, 1);

72      

73      for (int i = 2; i <= n + 1; i++){

74          if (A[i].a == 0) continue;

75          Lcm = (Lcm * A[i].b) / gcd(Lcm, A[i].b);

76      }

77      if (Lcm < 0) Lcm *= -1;

78      M *= Lcm;

79      printf("%lld", M);

80      for (int i = n + 1; i >= 0; i--) printf(" %lld", A[i].a * Lcm / A[i].b); 

81 }

82 

83 int main(){

84     

85     init();

86     work();

87     //printf("%lld\n", C[5][3]);

88     return 0;

89 }
View Code

 

你可能感兴趣的:(poj)