EOJ 1499 http://acm.cs.ecnu.edu.cn/problem.php?problemid=1499
此题是要求F数列(Fibonacci)f[n]的前n项和S[n];
注意到f[n] = f[n-1] + f[n-2],错项相加有
f[0] + f[1] + f[2] + ... + f[n-2] ~ S[n-2] (f[0] = 0)
+ f[1] + f[2] + f[3] + ... + f[n-1] ~ S[n-1]
-----------------------------------------------------
= f[2] + f[3] + f[4] + ... + f[n] ~ S[n] - f[1]
即 S[n] = S[n-1]+S[n-2]+1; (1)
由(1)易得
S[n]+1 为F数列,且 S[n] = f[n+2] - 1;
那么只需求出f[n+2], 其公式可参见PKU 3070 http://poj.org/problem?id=3070
所以这里用到了矩阵快速幂,基于对n的2进制分解,同快速模取幂——(a^b)%M,不赘述。
代码如下:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string> 4 #include <algorithm> 5 #include <string.h> 6 #include <stdlib.h> 7 #define M 100000000 8 9 using namespace std; 10 long long c[2][2]; 11 12 long long a0[2][2] = 13 { 14 1, 0, 15 0, 1 16 }; 17 long long a1[2][2] = 18 { 19 1, 1, 20 1, 0 21 }; 22 23 void matrixMulti(long long (*a)[2], long long (*b)[2], long long (*c)[2]) 24 { 25 for(int i=0; i<2; i++) 26 for(int j=0; j<2; j++) 27 { 28 long long sum = 0; 29 for(int k=0; k<2; k++) 30 sum = (sum + a[i][k]*b[k][j])%M; 31 c[i][j] = sum%M; 32 } 33 } 34 35 void matrixCpy(long long (*a)[2], long long (*t)[2]) 36 { 37 for(int i=0; i<2; i++) 38 for(int j=0; j<2; j++) 39 a[i][j] = t[i][j]; 40 } 41 42 int f(int n) 43 { 44 long long a[2][2]; 45 matrixCpy(a, a1); //a初始化为a1。 46 long long t[2][2]; //t是临时矩阵。 47 while(n) 48 { 49 if(n%2) 50 { 51 matrixMulti(c, a, t); 52 matrixCpy(c, t); 53 } 54 matrixMulti(a, a, t); 55 matrixCpy(a, t); 56 n /= 2; 57 } 58 return c[0][1]; 59 } 60 int main() 61 { 62 //freopen("testin.txt", "r", stdin); 63 //freopen("testout.txt", "w", stdout); 64 65 int n; 66 while(cin >> n) 67 { 68 matrixCpy(c, a0); //c初始化为a0(单位阵)。 69 70 printf("%d\n", f(n+2)-1); 71 } 72 73 return 0; 74 }