http://acm.whu.edu.cn/land/problem/detail?problem_id=1540
一道很简单的矩阵模版题,没有解出来真是打脸...
要你求斐波那契数列的每一项的三次方的前n项和。
解题思路:
要你求的是Sn 那么Sn = Sn-1 + Fx-1 ^ 3
(三个公式准备:
斐波那契数的Fx = Fx-1 + Fx-2
立方和公式 w^3 = (x + y)^3 = x^3 + 3x^2*y + 3x*y^2 + y^3;
平方和公式w^2 = (x + y)^2 = x^2 + 2*xy + y^2;)
构造一个矩阵,第一行的有5个项,分别是 Fn^3、Fn^2*Fn-1、Fn*Fn-1^2、Fn-1^3、Sn-1。
求Fn+1^3、Fn+1^2*Fn、Fn+1*Fn^2、Fn^3、Sn的情况。
然后就是利用三个公式凑出矩阵。
(得到的矩阵就是
1 1 1 1 1
3 2 1 0 0
3 1 0 0 0
1 0 0 0 0
0 0 0 0 1)
然后看一下代码吧:
#include <cstdio> #include <iostream> using namespace std; typedef long long ll; const int maxn = 5; const ll mod = 1000000007; struct Mat{ ll m[maxn][maxn]; void initRight() { m[0][0] = m[0][1] = m[0][2] = m[0][3] = m[0][4] = 1; m[1][0] = 3, m[1][1] = 2, m[1][2] = 1; m[2][0] = 3, m[2][1] = 1; m[3][0] = 1; m[4][4] = 1; } void initLeft() { m[0][0] = m[0][1] = m[0][2] = m[0][3] = m[0][4] = 1; } Mat() { for(int i = 0; i < maxn; i++) for(int j = 0; j < maxn; j++) m[i][j] = 0; } void zero() { for(int i = 0; i < maxn; i++) for(int j = 0; j < maxn; j++) m[i][j] = 0; } void one() { for(int i = 0; i < maxn; i++) for(int j = 0; j < maxn; j++){ m[i][j] = 0; if(i == j) m[i][j] = 1; } } Mat &operator = (const Mat &rhs) { for(int i = 0; i < maxn; i++) for(int j = 0; j < maxn; j++) m[i][j] = rhs.m[i][j]; return *this; } Mat operator * (const Mat &rhs) { Mat mat; mat.zero(); for(int i = 0; i < maxn; i++) for(int j = 0; j < maxn; j++) for(int k = 0; k < maxn; k++) mat.m[i][j] = (mat.m[i][j] + m[i][k]*rhs.m[k][j])%mod; return mat; } Mat operator ^ (const int &mi) { Mat ret, a; int b = mi; ret.one(); a = *this; while(b) { if(b & 1) ret = ret*a; a = a*a; b >>= 1; } return ret; } }; int main() { // freopen("data.in", "r", stdin); int n; Mat l, r, res; while(scanf("%d", &n) != EOF && n != 0) { l.zero(); r.zero(); l.initLeft(); r.initRight(); res = l * (r^(n-1)); printf("%lld\n", res.m[0][4]); } return 0; }