说道矩阵快速幂先要了解什么是矩阵什么是矩阵乘法、这更有利于我们理解矩阵快速幂
矩阵快速幂可以把一个 O(n)的效率提高 变成O(log(n))的效率其关键核心在于矩阵乘法的特征
比如A*A*A*A => (A*A)*(A*A) 很简单的就可以想到 B = A*A 原来的式子就会等去 B*B
这样一来我们可以先计算出 B 然后计算出B*B 答案就出来了 效率明显降低
接下来以POJ一道简单的题目为例 、并贴上我的代码
题目连接: http://poj.org/problem?id=3070
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9978 | Accepted: 7118 |
Description
In the Fibonacci integer sequence, F0 = 0, F1 = 1, and Fn = Fn − 1 + Fn − 2 for n ≥ 2. For example, the first ten terms of the Fibonacci sequence are:
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …
An alternative formula for the Fibonacci sequence is
Given an integer n, your goal is to compute the last 4 digits of Fn.
Input
The input test file will contain multiple test cases. Each test case consists of a single line containing n (where 0 ≤ n ≤ 1,000,000,000). The end-of-file is denoted by a single line containing the number −1.
Output
For each test case, print the last four digits of Fn. If the last four digits of Fn are all zeros, print ‘0’; otherwise, omit any leading zeros (i.e., print Fn mod 10000).
Sample Input
0 9 999999999 1000000000 -1
Sample Output
0 34 626 6875
Hint
As a reminder, matrix multiplication is associative, and the product of two 2 × 2 matrices is given by
Also, note that raising any 2 × 2 matrix to the 0th power gives the identity matrix:
以下是我的AC代码
#include
#define MOD 10000
using namespace std;
int a[2][2] ={1};
struct matrix
{
long long m[2][2];
};
matrix mul(matrix a , matrix b)
{
matrix res = {0,0,0,0};
for(int i = 0 ; i < 2 ; i++)
{
for(int j = 0 ; j < 2 ; j++)
{
for(int k = 0 ; k < 2 ; k++)
res.m[i][j] = (res.m[i][j] + a.m[i][k] * b.m[k][j]) % MOD;
}
}
return res;
}
int main()
{
int n;
while(cin>>n && n != -1)
{
matrix ans ={1,1,1,0}, s = ans;
while(n)
{
if(n&1)
ans = mul(ans,s);
n >>= 1;
s = mul(s,s);
}
cout << ans.m[1][1] << endl;
}
return 0;
}
矩阵的题目难点在于如何构造一个矩阵
下面附上一个3行3列的矩阵乘法模板 大家通过调试理解一下矩阵快速幂
#include
#include
#include
#include
using namespace std;
int N;
struct matrix
{
int a[3][3];
}origin,res;
matrix multiply(matrix x,matrix y)
{
matrix temp;
memset(temp.a,0,sizeof(temp.a));
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
for(int k=0;k<3;k++)
{
temp.a[i][j]+=x.a[i][k]*y.a[k][j];
}
}
}
return temp;
}
void init()
{
printf("随机数组如下:\n");
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
{
origin.a[i][j]=rand()%10;
printf("%8d",origin.a[i][j]);
}
printf("\n");
}
printf("\n");
memset(res.a,0,sizeof(res.a));
res.a[0][0]=res.a[1][1]=res.a[2][2]=1; //将res.a初始化为单位矩阵
}
void calc(int n)
{
while(n)
{
if(n&1)
res = multiply(res,origin);
n>>= 1;
origin=multiply(origin,origin);
}
printf("%d次幂结果如下:\n",n);
for(int i=0;i<3;i++)
{
for(int j=0;j<3;j++)
printf("%8d",res.a[i][j]);
printf("\n");
}
printf("\n");
}
int main()
{
while(cin>>N)
{
init();
calc(N);
}
return 0;
}