矩阵快速幂(矩阵加速)
//南昌理工ACM集训队
放心食用
- 矩阵加速
- 快速幂(前置技能)
- 矩阵快速幂
- 可乐
- 附个模板
- 最后小结
本人小白如有不对欢迎指正ლ(╹◡╹ლ)
矩阵加速
快速幂(前置技能)
对于普通的求a的b次方,一般我们用心算pow(a , b)就可以立马得到想要的数据,可是当b的值为1e8、1e9的时候,普通的乘法就无能为力了,因为乘一次花费的时间太长了,大大增加了时间成本。所以我们如何解决这个问题呢?
我们知道,任何一个正整数都可以由2的整数次幂相加得到,换句话说就是每个数都可以转化为二进制(不说也知道吧),所以我们发现只要b的2进制的第i位为1,就乘上a2ia ^ {2 ^ i }a2i (这个值可以在循环中得到)
放个模板,如果不是很懂可以搜一搜别的博客,就不细讲了
#define ll long long
ll power(ll a, ll b)//a^b
{ll ans = 1;while (b){if (b % 2 == 1) //当n为奇数时,乘以余下的一个aans *= a;a *= a;b /= 2;}return ans;
}
矩阵快速幂
那么我们能否将矩阵代入快速幂的方法
有三个矩阵 a * b = c,
我们知道矩阵与矩阵相乘,其中c[i][j]为A的第i行与B的第j列对应乘积的和,即
cij=∑k=1naik∗bkj\Large c \scriptsize i\scriptsize j=\displaystyle\sum_{k=1}^n \Large a \scriptsize i\scriptsize k* \Large b \scriptsize k\scriptsize j cij=k=1∑naik∗bkj
暴力循环小模板
juzhen mult(juzhen a, juzhen b) {juzhen c;for (int i = 0; i <= N; i++) {//N为矩阵的大小for (int j = 0; j <= N; j++) {for (int k = 0; k <= N; k++) {c.m[i][j] = (c.m[i][j] + a.m[i][k] * b.m[k][j]);}}}return c;
}
带进前面的快速幂的模板里,就是矩阵快速幂一开始的样子
juzhen result;
void juzhenPower(juzhen A, ll power) {while (power) {if (power & 1)result = mult(result, A);power /= 2;A = mult(A, A);}
}
当然,根据性质,1乘任何数都等于那个数,所以我们初始化的result矩阵乘任何矩阵都应该等于那个矩阵,所以根据矩阵的性质,我们可以用形如
(100010001)\begin{pmatrix} 1 & 0&0 \\ 0& 1& 0 \\ 0 & 0 & 1 \end{pmatrix} ⎝⎛100010001⎠⎞
的矩阵,就是左上到右下对角线都为1,其他数为0的矩阵。
那么矩阵快速幂该如何使用呢
可乐
洛谷传送门
acwing传送门(yxcyyds)
这题在洛谷也有数据减弱的版本可以用dp水过,当然我建议一步到位,直接矩阵加速ac两题,双倍快乐(
题意:有N个城市,给出M条城市之间的道路,有一个机器人有随机三种操作
① 停在原地
② 去下一个相邻的城市
③ 自爆
给出t时间,每秒机器人执行一种操作,问t秒内机器人有多少种操作。
对于 100% 的数据, n,m≤100 , t≤10^9。
我们不难发现,n与m不是很大,但是t却大的离谱,建议机器人原地自爆
在大学的离散数学课中,我们学过用矩阵构造路径,去求有多少种路径的方法。在这题里,n与m最大只有100,也就是边长为100的矩阵,t为10 ^ 9,也就是将这个矩阵乘上10 ^ 9次方。利用矩阵快速幂的方法,我们也就可以求出我们需要的值。
那么我们按照构造路径的方法构造这个矩阵
设基础矩阵为base[ N ][ N ],base[ i ][ j ]表示从 i 到 j有多少种方法。当然最后求出的值就是base[ 1 ]上所有值的和
将样例
3 2
1 2
2 3
2
代入,可以构造出类似
(1000111011111011)\begin{pmatrix} 1 &0&0 &0 \\ 1& 1 &1&0 \\ 1 &1&1 & 1 \\ 1 &0&1 & 1 \\ \end{pmatrix} ⎝⎜⎜⎛1111011001110011⎠⎟⎟⎞
的矩阵,第0列的意思为从 i 到 0 ,也就是机器人的自爆,第 i 到 i 的意思为机器人站着不动,也就是花了一秒时间罚站。那么我们只要把这个矩阵乘 t 次方,就可以得到最后的记录方法数量的矩阵,将base[ 1 ]上所有的数相加,就能得到最终的答案
ac代码
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
const int mod = 2017;
ll N, M;
struct juzhen {ll m[101][101];
}x;
juzhen base, result;
juzhen az(juzhen a, juzhen b) {//暴力矩阵相乘juzhen c;memset(c.m, 0, sizeof(c.m));for (int i = 0; i <= N; i++) {for (int j = 0; j <= N; j++) {for (int h = 0; h <= N; h++) {c.m[i][j] = (c.m[i][j] + a.m[i][h] * b.m[h][j] % mod) % mod;}}}return c;
}
void juzhenPower(juzhen A, ll power) {//快速幂模板while (power) {if (power & 1)result = az(result, A);power /= 2;A = az(A, A);}
}
int main() {ll x, y, t, ans = 0;cin >> N >> M;for (int i = 0; i <= N; i++) {//将基础矩阵初始化base.m[i][i] = 1;base.m[i][0] = 1;}for (int i = 1; i <= N; i++) {//初始化result矩阵,也就是那个乘任意矩阵都等于那个矩阵的矩阵result.m[i][i] = 1;}for (int i = 0; i < M; i++) {//将连线代入到基础矩阵中cin >> x >> y;base.m[x][y] = 1;base.m[y][x] = 1;}cin >> t;juzhenPower(base, t);//将基础矩阵乘上t次for (int i = 0; i <= N; i++) {ans = (ans + result.m[1][i]) % mod;}cout << ans;//轻松ac
}
附个模板
矩阵相乘的部分有奆佬有时间复杂度为O( N^2.7)的方法,感兴趣的自己可以搜一搜
#define ll long long
juzhen cheng(juzhen a, juzhen b,ll mod) {//边长为N的两个矩阵相乘juzhen c;for (int i = 0; i <= N; i++) {for (int j = 0; j <= N; j++) {for (int h = 0; h <= N; h++) {c.m[i][j] = (c.m[i][j] + a.m[i][h] * b.m[h][j] % mod) % mod;}}}return c;
}
juzhen juzhenPower(juzhen A, ll n,ll mod) {//矩阵A的n次方,对mod取模,放心复制粘贴juzhen result;for (int i = 1; i <= N; i++) result.m[i][i] = 1;//初始化resultwhile (n) {if (n & 1)result = cheng(result, A , mod);n /= 2;A = cheng(A, A, mod);}return result;
}
最后小结
当我们能将问题转化成求A矩阵的T次方时,我们就可以考虑能否用矩阵快速幂求出此题的答案,当然还要思考如何构造初始矩阵,当你能推出线性的状态转移方程时就可以根据状态转移方程构造初始矩阵,来解决类似的问题。
矩阵快速幂(矩阵加速)相关推荐
- 矩阵小专题(矩阵快速幂+矩阵加速)
1.什么是矩阵? 矩阵(数学术语)_百度百科 2.矩阵快速幂 首先要知道,只有n*n的矩阵能乘以自身(否则不符合矩阵相乘的条件) 然后要明白普通的快速幂的原理(本质是把幂次二分,代码如下) inlin ...
- 51nod 1113 矩阵快速幂 (矩阵的n次方)
给出一个N * N的矩阵,其中的元素均为正整数.求这个矩阵的M次方.由于M次方的计算结果太大,只需要输出每个元素Mod (10^9 + 7)的结果. Input 第1行:2个数N和M,中间用空格分隔. ...
- 1647:迷路(矩阵快速幂+矩阵点的拆分)
1647:迷路 时间限制: 1000 ms 内存限制: 524288 KB 提交数: 97 通过数: 69 [题目描述] 原题来自:SCOI 2009 Windy 在有向图中迷路了. 该有向图有 N ...
- 矩阵快速幂---BestCoder Round#8 1002
当要求递推数列的第n项且n很大时,怎么快速求得第n项呢? 可以用矩阵快速幂来加速计算. 我们可以用矩阵来表示数列递推公式 比如fibonacci数列 可以表示为 [f(n) f(n-1)] = [ ...
- 快速幂、矩阵快速幂、快速乘法
快速幂 快速幂是我们经常用到的一种算法,快速幂顾名思义就是快速的幂运算.我们在很多题目中都会遇到幂运算,但是在指数很大的时候,我们如果用for或者是pow就会超时,这时候就用到了快速幂. 快速幂的原理 ...
- 矩阵问题入门(矩阵乘法and矩阵快速幂)acm寒假集训日记22/1/15
今天凌晨3点才睡,没想到通过看小说抑制玩游戏,反而看小说的时间更长. u1s1:那小说太刺激了,晚上看很有感觉,风吹草动我就会猛地看过去(类似茄子说柜子动了,哈哈),真TM(语气词)练胆量!!!..Q ...
- 矩阵相关操作和矩阵快速幂
矩阵相关操作和矩阵快速幂 矩阵基本运算以及快速幂模板 POJ - 3070. Fibonacci Hdu - 1757A. Simple Math Problem Codeforces - 185A. ...
- 数论-快速幂、矩阵快速幂、慢速乘
文章目录 快速幂 矩阵快速幂 慢速乘 例题 HDU-2817 HDU-3117 XUJC-1395 快速幂 首先幂运算 a n a^n an就是 n n n个 a a a相乘,我们可以直接调用库函数 ...
- 快速幂+矩阵快速幂(总结+例题)
1.快速幂 以求a的b次方来介绍: 首先把b转换成二进制数 该二进制数第i位的权为 2^i - 1 . 比如 : 11的二进制是1011 11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1 ...
- 矩阵快速幂详解--用矩阵幂解决的多种问题
最经典的题目 以及洛谷一大堆相似题斐波那契升级版,广义斐波那契等等,都是相关的题目.一般而言我们求解斐波那契无非是不断地向前迭代,但是这样的效率实在是太低了.对于nnn的规模如此之大的题目应该如何求解 ...
最新文章
- mysql 小型机_小型机宕机问题 - Oracle数据库管理 - ITPUB论坛-中国专业的IT技术社区...
- JAVA反射通俗易懂转 转载大牛的 通俗易懂
- numpy.power()
- MySQL删除普通用户
- Python数据库添加时间
- 修改Xmodem/Zmodem上传下载路径
- 在互联网行业Java程序员的工资标准是多少呢?
- 近代数字信号处理实验-DFT分析信号的频谱
- 02331数据结构 散列表
- 【Docker】OCI runtime exec failed: exec failed: container_linux.go:348: starting container process cau
- android excel 筛选功能,Android 实现 Excel 解析 xls 和 xlsx,方法也可以很简单
- html5+css3方式实现mobie app的一些瓶颈
- k8s中本地存储卷emptyDir、hostPath卷
- GIS投影、坐标系、坐标系转换
- 火星坐标 C语言,坐标
- c++算法解决力扣跳步问题
- 数据库原理第三章习题作业
- vue中用装饰器报错:Parsing error: Decorators cannot be used to decorate object literal properties
- ff14服务器维护时间,《FF14》10月15日国服维护到几点 5.0新版本更新维护公告
- thinksnsv4.6运行php,ThinkSNS开启调试模式
热门文章
- 分享一个有意思的游戏
- ESP32 Arduino Ticker定时库
- 记录:ERROR YarnScheduler: Lost executor 2 on XXX: Container killed by YARN for exceeding memory limits
- 【每日最爱一句】2013.07.18
- java jmf获取图像_java利用jmf实现拍照功能
- 0基础快速开发口袋网盘小程序
- 图形虚拟化技术为每个英特尔®显卡家族提供支持
- 微信开发 没有认证过的服务号怎么办?微信提供了测试号(开通了认证过的服务号的功能)
- 十沣科技TF-Dyna不亚于国际主流商业软件 应用领域广泛
- 58金融客服电话--24小时全国统一服务热线