高木さんBlog高木さん

矩阵快速幂

矩阵快速幂

矩阵快速幂

一类经常出现在优化问题中的数学方法

快速幂#

给定 a,b,p , 求出 abmodp 的值
其中1a,b,p2×109
对于这种求极大数的乘方问题,我们都利用快速幂来解决
b=bi
可以得到 ab=abi=abi
对于b的拆分我们使用二进制拆位的思想,这样b会拆成2x0+2x1+...+2xn的形式
那么对于计算有什么好处呢
对于连续的x1=x0+1而言,a2x1=a2x0+1=a22x0=(a2x0)2
这样我们就可以迭代了

Copy
a = a * a;

n次幂的计算时间复杂度由O(n)降至O(logn)

Copy
LL qmi(int a ,int b ,int p) { LL res = 1 % p; while(b) { if(b & 1) res = res * a % p; a = (LL) a * a % p; b >>= 1; } return res; }

然后是矩阵快速幂的问题
我们知道幂运算不只是对实数域有用,复数域,矩阵同样适用
对于Ak的计算,优化思路是相同的,对于k进行二进制分解,只不过乘法面对的不再是数字,而是矩阵
所以运算符重载和定义乘法函数均可

Copy
void mul(int c[][N] , int a[][N] , int b[][N]) // c = a * b { static int t[N][N]; memset(t , 0 , sizeof t); for(int i = 0 ; i < N ; i ++) for(int j = 0 ; j < N ; j ++) for(int k = 0 ; k < N ; k ++) t[i][j] = (t[i][j] + (LL) a[i][k] * b[k][j]) % p; memcpy(t , c , sizeof t); } void qmi(int a[][N] , int n) { int res[N][N]; for(int i = 0 ; i < N ; i ++) res[i][i] = 1; while (n) { if (n & 1) mul(res, res, w); mul(w, w, w); n >>= 1; } }

然后就是针对实际问题了
比如求Fibonacci数列
我们知道Fibonacci的递推式
fn=fn1+fn2
那我们构造一个向量Fn=[fnfn+1]
可知Fn+1=[fn+1fn+2]
那么 Fn+1=[fn+1fn+fn+1]
改写成矩阵形式Fn+1=[fnfn+1][0111]
Fn+1=Fn[0111]
可得Fn=F0[0111]n
剩下就可以交给快速幂了

这样由原来的O(n) 优化到了O(logn)

posted @   她说戴了不算給  阅读(16)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示
目录