矩阵快速幂
Posted xj22yangyichen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了矩阵快速幂相关的知识,希望对你有一定的参考价值。
矩阵乘法
定义矩阵乘法的运算规则如下
其中 \\(C\\left[i\\right]\\left[j\\right]\\) 等于 \\(A\\) 的第 \\(i\\) 行乘 \\(B\\) 的第 \\(j\\) 列,举例如下
矩阵乘法的性质
- 满足分配率和结合律,不满足交换率
- \\(A\\) 的列数必须等于 \\(B\\) 的行数
用斐波那契数列引入矩阵快速幂
已知斐波那契数列
其中
则有
求解广义斐波那契数列
广义斐波那契数列数列的公式
则有
求解系数含有0的递推函数
已知公式
则有
将系数为0的项对应的矩阵中的位置置0
求解一般递推函数
已知公式
则有
将常数项加入待求的矩阵中一并运算,并将计算矩阵相对应的位置置1以确保常数项的值不变
求解有下标的递推函数
已知公式
这里需要用到一个知识:立方的展开
事实上,矩阵乘法求递归问题也可以用纵向的矩阵表示,如下
快速幂计算(整数快速幂/矩阵快速幂)
//*************快速幂计算****************************************
朴素算法实现:
1 ll get_pow(ll x, ll n) //** (这里的n要求不小于0,如果n小于0则令n=-n,并且最终返回1.0/ans即可) 2 { 3 ll ans=1; 4 while(n--) 5 { 6 ans*=x%MAX; 7 ans%=MAX; 8 } 9 return ans; 10 }
快速幂算法:
原理:
二分:
假设我们现在要计算pow(x,n),那么有当n为偶数时pow(x, n)==pow(x*x, n/2),当n为奇数时,pow(x, n)==pow(x, n-1)*x, 此时n-1为偶数,可按前面的公式继续迭代;
循环往复,即可计算出答案;
二进制:
计算pow(x,n),先将n转化为二进制形式,n=2^a+2^b....
例如:计算pow(x,21),19=2^4+2^2+2^1;其中2^2可以由(2^1)*(2^1)得到,同理, 2^4可以由(2^2)*(2^2)得到;
所有有pow(x,21)==x^(2^4+2^2+2^1),其时间复杂度为o(long2(n));
以上两种思路的出发点不同,不过其本质一致,代码也相同;
代码:
1 ll get_pow(ll x, ll n) //** (这里的n要求不小于0,如果n小于0则令n=-n,并且最终返回1.0/ans即可) 2 { 3 int ans=1; 4 while(n) 5 { 6 if(n&1) 7 { 8 ans=(ans*x)%MAX; 9 } 10 x=(x*x)%MAX; 11 n>>=1; 12 } 13 return ans; 14 }
//*********************矩阵快速幂计算**********************************
矩阵快速幂和快速幂算法原理一样,只是操作对象换成了矩阵;
http://acm.nyist.net/JudgeOnline/problem.php?pid=148(题目链接)
ac代码:
1 #include <bits/stdc++.h> 2 #define MAXN 2 3 #define mod 10000 4 #define ll long long 5 using namespace std; 6 7 struct Matrix 8 { 9 ll x[MAXN][MAXN]; 10 }; 11 12 Matrix temp={1, 1, 1, 0}; 13 14 ll n; //***n为幂数,结果对mod取模 15 16 Matrix multi(Matrix a, Matrix b) //***矩阵乘法 17 { 18 Matrix c; 19 memset(c.x, 0, sizeof(c.x)); 20 for(int i=0; i<MAXN; i++) 21 { 22 for(int j=0; j<MAXN; j++) 23 { 24 for(int k=0; k<MAXN; k++) 25 { 26 c.x[i][j]+=(a.x[i][k]*b.x[k][j])%mod; 27 } 28 } 29 } 30 return c; 31 } 32 33 ll Pow(ll n) 34 { 35 Matrix ans; 36 temp.x[0][0]=temp.x[0][1]=temp.x[1][0]=1; 37 temp.x[1][1]=0; 38 memset(ans.x, 0, sizeof(ans.x)); 39 ans.x[0][0]=ans.x[1][1]=1; 40 while(n) 41 { 42 if(n&1) ans=multi(ans, temp); 43 temp=multi(temp, temp); 44 n>>=1; 45 } 46 return ans.x[0][1]; 47 } 48 49 int main(void) 50 { 51 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); 52 while(cin >> n && n!=-1) 53 { 54 cout << Pow(n)%mod << endl; 55 } 56 return 0; 57 }
以上是关于矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章