【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 ik 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 Sk(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, ak+1, ak, ... , a1, a0) 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, ak+1, ak, ... , a1, a0 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

 

posted @ 2015-03-31 09:07  TCtower  阅读(302)  评论(0编辑  收藏  举报