HDU 1005 Number Sequence:矩阵快速幂
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1005
题意:
数列{f(n)}: f(1) = 1, f(2) = 1, f(n) = ( A*f(n-1) + B*f(n-2) ) MOD 7
给定A、B、n,求f(n)。 (1<=n<=100,000,000)
题解:
大水题~ (*/ω\*)
矩阵快速幂。
初始矩阵start:
特殊矩阵special:
所求矩阵ans:
ans = start * special^(n-1)
ans的第一项即为f(n)。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #define MAX_L 5 5 #define MOD 7 6 7 using namespace std; 8 9 struct Mat 10 { 11 int n; 12 int m; 13 int val[MAX_L][MAX_L]; 14 Mat() 15 { 16 n=0; 17 m=0; 18 memset(val,0,sizeof(val)); 19 } 20 }; 21 22 int a,b,n; 23 24 Mat make_unit(int n) 25 { 26 Mat mat; 27 mat.n=n; 28 mat.m=n; 29 for(int i=0;i<n;i++) 30 { 31 mat.val[i][i]=1; 32 } 33 return mat; 34 } 35 36 Mat make_start() 37 { 38 Mat mat; 39 mat.n=1; 40 mat.m=2; 41 mat.val[0][0]=1; 42 mat.val[0][1]=1; 43 return mat; 44 } 45 46 Mat make_special() 47 { 48 Mat mat; 49 mat.n=2; 50 mat.m=2; 51 mat.val[0][0]=0; 52 mat.val[0][1]=b; 53 mat.val[1][0]=1; 54 mat.val[1][1]=a; 55 return mat; 56 } 57 58 Mat mul_mat(const Mat &a,const Mat &b) 59 { 60 Mat c; 61 if(a.m!=b.n) 62 { 63 cout<<"Error: mat_mul"<<endl; 64 return c; 65 } 66 c.n=a.n; 67 c.m=a.m; 68 for(int i=0;i<a.n;i++) 69 { 70 for(int j=0;j<b.m;j++) 71 { 72 for(int k=0;k<a.m;k++) 73 { 74 c.val[i][j]+=a.val[i][k]*b.val[k][j]; 75 c.val[i][j]%=MOD; 76 } 77 } 78 } 79 return c; 80 } 81 82 Mat quick_pow_mat(Mat mat,long long k) 83 { 84 Mat ans; 85 if(mat.n!=mat.m) 86 { 87 cout<<"Error: quick_pow_mat"<<endl; 88 return ans; 89 } 90 ans=make_unit(mat.n); 91 while(k) 92 { 93 if(k&1) 94 { 95 ans=mul_mat(ans,mat); 96 } 97 mat=mul_mat(mat,mat); 98 k>>=1; 99 } 100 return ans; 101 } 102 103 int main() 104 { 105 while(cin>>a>>b>>n) 106 { 107 if(a==0 && b==0 && n==0) break; 108 Mat start=make_start(); 109 Mat special=make_special(); 110 Mat ans=mul_mat(start,quick_pow_mat(special,n-1)); 111 cout<<ans.val[0][0]<<endl; 112 } 113 }