Problem Description
小
H是一个程序员。他很喜欢做各种各样的数学题,尤其喜欢做《水泥数学》。
在看了《水泥数学》的
2.5章后,小
H终于会用
9种计算
1^2+2^2+...+n^2了!这两天,他一直在思考一个加强的问题。他想要计算
1^k+...+n^k。
通过思考,他发现对所有
k,
P(n)=1^k+...+n^k可以表示成一个最高次数为
k+1的有理系数多项式。比方说当
k=1时
P(n)=n(n+1)/2.
现在,对某个
k,小
H想知道
P(n)的系数。
Input
第一行为一个整数
t(
1 <= t <= 31),表示有
t组测试数据;
下面
T行每行一个正整数
k(
0 <= k<= 30),表示一组数据。
Output
对于每个输入
k,输出一行
k+2个分数,依次给出此时
P(n)=a_{k+1} n^{k+1}+...+a_1 n+a_0的系数
a_{k+1},
....,
a_0。所有分数必须以
“a/b”的形式给出,其中
a和
b为整数且互质,
b>0;如果某一项为
0,输出
“0/1”。
Sample Input
2
1
2
Sample Output
1/2 1/2 0/1
1/3 1/2 1/6 0/1
二、 解题思路:
递推公式如下:
\sum_{i=1}^n i^{k+1}
=\sum_{i=0}^{n-1} (i+1)^{k+1}
=\sum_{i=0}^{n-1} ( \sum_{j=0}^{k+1} \binom{k+1}{j} i^j)
=\sum_{i=0}^{n-1} ( i^{k+1} + (k+1) i^k + \sum_{j=0}^{k-1} \binom{k+1}{j} i^j)
=\sum_{i=0}^{n-1} i^{k+1} + (k+1) \sum_{i=0}^{n-1} i^k + \sum_{i=0}^{n-1} ( \sum_{j=0}^{k-1} \binom{k+1}{j} i^j)
=\sum_{i=1}^{n-1} i^{k+1} + (k+1) \sum_{i=1}^{n-1} i^k + \sum_{j=0}^{k-1} \binom{k+1}{j} (\sum_{i=1}^{n-1} i^j)
so
n^{k+1} = (k+1) \sum_{i=1}^{n-1} i^k + \sum_{j=0}^{k-1} \binom{k+1}{j} (\sum_{i=1}^{n-1} i^j)
(k+1) \sum_{i=1}^{n-1} i^k = n^{k+1} + \sum_{j=0}^{k-1} \binom{k+1}{j} (\sum_{i=1}^{n-1} i^j)
(k+1) \sum_{i=1}^{n} i^k = (n+1)^{k+1} + \sum_{j=0}^{k-1} \binom{k+1}{j} (\sum_{i=1}^{n} i^j)
\sum_{i=1}^{n} i^k = ( (n+1)^{k+1} + \sum_{j=0}^{k-1} \binom{k+1}{j} (\sum_{i=1}^{n} i^j) )/ (k+1)
#include <iostream> #include <cstdio> using namespace std; typedef long long LL; const int MAXN=33; LL C[MAXN][MAXN]; LL ca[MAXN][MAXN], cb[MAXN][MAXN]; int n; LL gcd(LL a, LL b) { return b==0 ? a : gcd(b,a%b); } void adjust(LL &a, LL &b) { LL k=gcd(a, b); a/=k, b/=k; if(b<0) a=-a, b=-b; } void add(LL &a, LL &b, LL xa, LL xb) { adjust(a, b); adjust(xa, xb); LL k=gcd(b, xb); LL u=b/k, ub=xb/k; a*=ub; b*=ub; xa*=u; xb*=u; a+=xa; adjust(a, b); } int main() { int cs; for(cin>>cs; cs--; ) { for(int i=0; i<MAXN; ++i) C[0]=C=1LL; for(int i=1; i<MAXN; ++i) for(int j=1; j<i; ++j) C[j]=C[i-1][j-1]+C[i-1][j]; cin>>n; ca[0][0]=0, cb[0][0]=1; ca[0][1]=1, cb[0][1]=1; for(int k=1; k<=n; ++k) { for(int i=0; i<=k+1; ++i) { ca[k]=0; cb[k]=1; } for(int i=0; i<=k+1; ++i) add(ca[k], cb[k], C[k+1], 1); for(int i=0; i<=k-1; ++i) for(int j=0; j<=i+1; ++j) add(ca[k][j], cb[k][j], -ca[j]*C[k+1], cb[j]); add(ca[k][0], cb[k][0], -1, 1); for(int i=0; i<=k+1; ++i) { cb[k]*=(LL)(k+1); adjust(ca[k], cb[k]); } } for(int i=n+1; i>=0; --i) cout<<ca[n]<<"/"<<cb[n]<<(i>0?' ':'\n'); } return 0; }