第二讲-乘方取模和矩阵快速幂

合集下载

矩阵快速幂欧拉定理

矩阵快速幂欧拉定理

矩阵快速幂欧拉定理
矩阵快速幂欧拉定理是一种高效的算法,通常用于解决大数取模的问题。

其核心思想是将底数进行分解,利用欧拉定理对每个因子进行求幂,再对结果进行合并,最终得到正确的答案。

具体而言,将底数a拆分为若干个质数的积,例如a=p1^k1 *
p2^k2 * ... * pn^kn。

然后对于每个质数pi,使用欧拉定理进行求幂,即:
a^b ≡ (a mod m)^b mod m ≡ ((a mod pi)^b mod pi) * ((a/p1^k1 mod pi)^b mod pi) * ... * ((a/pn^kn mod pi)^b mod pi) (mod pi)
最后将每个pi的结果使用中国剩余定理合并即可得到最终答案。

而矩阵快速幂则是一种优化的算法,它可以利用矩阵乘法的性质,将若干个底数的求幂问题合并为一个矩阵的求幂问题,从而大幅降低时间复杂度。

总之,矩阵快速幂欧拉定理是一种非常强大的算法,可以在处理大数取模问题时发挥重要作用。

学好这个算法,对于提高程序效率和解决复杂问题都有很大帮助。

- 1 -。

矩阵快速幂取模

矩阵快速幂取模

矩阵快速幂取模参考博客1:据说,矩阵快速幂在递推式优化上相当神奇,⽽且效率很⾼。

两矩阵相乘,朴素算法的复杂度是O(N^3)。

如果求⼀次矩阵的M次幂,按朴素的写法就是O(N^3*M)。

既然是求幂,不免想到快速幂取模的算法,有快速幂取模的介绍,a^b %m 的复杂度可以降到O(logb)。

如果矩阵相乘是不是也可以实现O(N^3 * logM)的时间复杂度呢?答案是肯定的。

先定义矩阵数据结构: struct Mat {double mat[N][N];}; O(N^3)实现⼀次矩阵乘法Mat operator * (Mat a, Mat b) {Mat c;memset(c.mat, 0, sizeof(c.mat));int i, j, k;for(k = 0; k < n; ++k) {for(i = 0; i < n; ++i) {if(a.mat[i][k] <= 0) continue; //(针对ZOJ2853)剪枝,cpu运算乘法的效率并不是想像的那么理想(加法的运算效率⾼于乘法,⽐如Strassen矩阵乘法)for(j = 0; j < n; ++j) {if(b.mat[k][j] <= 0) continue; //剪枝c.mat[i][j] += a.mat[i][k] * b.mat[k][j];}}}return c;} 下⾯介绍⼀种特殊的矩阵:单位矩阵很明显的可以推知,任何矩阵乘以单位矩阵,其值不改变。

有了前边的介绍,就可以实现矩阵的快速连乘了。

Mat operator ^ (Mat a, int k) {Mat c;int i, j;for(i = 0; i < n; ++i)for(j = 0; j < n; ++j)c.mat[i][j] = (i == j); //初始化为单位矩阵for(; k; k >>= 1) {if(k&1) c = c*a;a = a*a;}return c;} 举个例⼦: 求第n个Fibonacci数模M的值。

快速幂取模算法详解

快速幂取模算法详解

快速幂取模算法详解转载https:///ltyqljhwcm/article/details/53043646 article>1.⼤数模幂运算的缺陷:快速幂取模算法的引⼊是从⼤数的⼩数取模的朴素算法的局限性所提出的,在朴素的⽅法中我们计算⼀个数⽐如5^1003%31是⾮常消耗我们的计算资源的,在整个计算过程中最⿇烦的就是我们的5^1003这个过程缺点1:在我们在之后计算指数的过程中,计算的数字不都拿得增⼤,⾮常的占⽤我们的计算资源(主要是时间,还有空间)缺点2:我们计算的中间过程数字⼤的恐怖,我们现有的计算机是没有办法记录这么长的数据的,所以说我们必须要想⼀个更加⾼效的⽅法来解决这个问题2.快速幂的引⼊:我们⾸先从优化的过程开始⼀步⼀步优化我们的模幂算法1.朴素模幂运算过程:1. #define ans=12. for(int i=1;i<=b;i++)3. {4. ans*=a;5. }根据我们上⾯说的,这种算法是⾮常的⽆法容忍的,我们在计算的过程中出现的两个缺点在这⾥都有体现在这⾥我们如果要做优化的话,我肥就是每个过程中都加⼀次模运算,但是我们⾸先要记住模运算是⾮常的消耗内存资源的,在计算的次数⾮常的⼤的时候,我们是没有办法忍受这种时间耗费的2.快速幂引⼊:在讲解快速幂取模算法之前,我们先将⼏个必备的知识1.对于取模运算:(a*b)%c=(a%c)*(b%c)%c这个是成⽴的:也是我们实现快速幂的基础之后我们来看看快速幂的核⼼本质我通过离散课上的学习,将快速幂的本质差不多理解了⼀下,感觉还是很深刻的在这⾥,我们对指数懂了⼀些⼿脚,核⼼思想在于将⼤数的幂运算拆解成了相对应的乘法运算,利⽤上⾯的式⼦,始终将我们的运算的数据量控制在c的范围以下,这样我们可以客服朴素的算法的缺点⼆,我们将计算的数据量压缩了很⼤⼀部分,当指数⾮常⼤的时候这个优化是更加显著的,我们⽤Python来做⼀个实验来看看就知道我们优化的效率有多⾼了1. from time import *2. def orginal_algorithm(a,b,c): #a^b%c3. ans=14. a=a%c #预处理,防⽌出现a⽐c⼤的情况5. for i in range(b):6. ans=(ans*a)%c7. return ans8.9. def quick_algorithm(a,b,c):10. a=a%c11. ans=112. #这⾥我们不需要考虑b<0,因为分数没有取模运算13. while b!=0:14. if b&1:15. ans=(ans*a)%c16. b>>=117. a=(a*a)%c18. return ans19.20. time=clock()21. a=eval(input(“底数:”))22. b=eval(input(“指数:”))23. c=eval(input(“模:”))24. print(“朴素算法结果%d”%(orginal_algorithm(a,b,c)))25. print(“朴素算法耗时:%f”%(clock()-time))26. time=clock()27. print(“快速幂算法结果%d”%(quick_algorithm(a,b,c)))28. print(“快速幂算法耗时:%f”%(clock()-time))实验结果:4. 朴素算法结果55. 朴素算法耗时:3.2899526. 快速幂算法结果57. 快速幂算法耗时:0.006706我们现在知道了快速幂取模算法的强⼤了,我们现在来看核⼼原理:1. 对于任何⼀个整数的模幂运算2. a^b%c3. 对于b我们可以拆成⼆进制的形式4. b=b0+b1*2+b2*2^2+…+bn*2^n5. 这⾥我们的b0对应的是b⼆进制的第⼀位6. 那么我们的a^b运算就可以拆解成7. a^b0*a^b1*2*…*a^(bn*2^n)8. 对于b来说,⼆进制位不是0就是1,那么对于bx为0的项我们的计算结果是1就不⽤考虑了,我们真正想要的其实是b的⾮0⼆进制位9.10. 那么假设除去了b的0的⼆进制位之后我们得到的式⼦是11. a^(bx*2^x)*…*a(bn*2^n)12. 这⾥我们再应⽤我们⼀开始提到的公式,那么我们的a^b%c运算就可以转化为13. (a^(bx*2^x)%c)*…*(a^(bn*2^n)%c)14. 这样的话,我们就很接近快速幂的本质了1. (a^(bx*2^x)%c)*…*(a^(bn*2^n)%c)2. 我们会发现令3. A1=(a^(bx*2^x)%c)4. …5. An=(a^(bn*2^n)%c)6. 这样的话,An始终是A(n-1)的平⽅倍(当然加进去了取模匀速那),依次递推现在,我们基本的内容都已经了解到了,现在我们来考虑实现它:1. int quick(int a,int b,int c)2. {3. int ans=1; //记录结果4. a=a%c; //预处理,使得a处于c的数据范围之下5. while(b!=0)6. {7. if(b&1) ans=(ans*a)%c; //如果b的⼆进制位不是0,那么我们的结果是要参与运算的8. b>>=1; //⼆进制的移位操作,相当于每次除以2,⽤⼆进制看,就是我们不断的遍历b的⼆进制位9. a=(a*a)%c; //不断的加倍10. }11. return ans;12. }现在,我们的快速幂已经讲完了我们来⼤致的推演⼀下快速幂取模算法的时间复杂度⾸先,我们会观察到,我们每次都是将b的规模缩⼩了2倍那么很显然,原本的朴素的时间复杂度是O(n)快速幂的时间复杂度就是O(logn)⽆限接近常熟的时间复杂度⽆疑逼朴素的时间复杂度优秀很多,在数据量越⼤的时候,者中优化效果越明显3.OJ例题POJ1995题意:快速幂版题1. #include“iostream”2. #include“cstdio”3. #include“cstring”4. #include“cstdlib”5.6. using namespace std;7.8. int ans=0;9. int a,b;10. int c;11.12. int quick(int a,int b,int c)13. {14. int ans=1;15. a=a%c;16. while(b!=0)17. {18. if(b&1) ans=(ans*a)%c;19. b>>=1;20. a=(a*a)%c;24.25. int main()26. {27. int for_;28. int t;29. scanf(“%d”,&t);30. while(t–)31. {32. ans=0;33. scanf(“%d%d”,&c,&for_);34. for(int i=1;i<=for_;i++)35. {36. scanf(“%d%d”,&a,&b);37. ans=(ans+quick(a,b,c))%c;38. }39. printf(“%d\n”,ans);40. }41. return 0;42. }</div></div></article>。

矩阵乘法快速幂

矩阵乘法快速幂

矩阵乘法快速幂矩阵快速幂算法可以用于计算矩阵的幂。

假设有一个 n * n 的矩阵 A,需要计算 A 的 m 次幂,其中 m 是非负整数。

矩阵快速幂算法的基本思想是通过分治法将矩阵的幂运算化简为多个矩阵的乘法运算。

具体步骤如下:1. 初始化一个单位矩阵 I,它的每个元素 A[i][j] = 1 当且仅当 i = j,其余元素都为 0。

2. 将矩阵 A 和单位矩阵 I 分别初始化为两个 n * n 的矩阵。

3. 将矩阵 A 逐步平方,即计算 A^2, A^4, A^8, ..., A^m,直到指数大于等于 m。

4. 对于每个指数 k,将 I 与 A^(2^k) 相乘,即计算 I * A^(2^k)。

5. 最后得到的矩阵 I 就是 A 的 m 次幂。

矩阵的乘法可以利用分块矩阵的性质进行加速。

假设 A 和 B是两个 n * n 的矩阵,其中 n = 2^k,可以将 A 和 B 分成大小为 n/2 * n/2 的四个子矩阵,并依次计算它们的乘积。

这样可以将原来的矩阵乘法的时间复杂度从 O(n^3) 降低为 O(n^2)。

总结起来,矩阵快速幂算法的时间复杂度为 O(n^3 * log m),其中 n 是矩阵的大小,m 是指数。

下面是一个示例代码,用于计算矩阵的快速幂:```pythonimport numpy as npdef matrix_power(matrix, power):result = np.eye(matrix.shape[0], dtype=int)while power > 0:if power % 2 == 1:result = np.dot(result, matrix)matrix = np.dot(matrix, matrix)power //= 2return result```这个代码使用了 NumPy 库来表示和操作矩阵。

函数`matrix_power` 接受一个矩阵和一个非负整数作为参数,返回计算结果。

数论——乘法逆元(快速幂求法)及模运算

数论——乘法逆元(快速幂求法)及模运算

数论——乘法逆元(快速幂求法)及模运算⼀、快速幂原理: 快速幂的原理⼗分简单。

a k=a2^0*a2^1*a2^2*...a2^x,其中k=20+21+22+ (2x) 这显然是正确的。

因为任何⼀个数都可以表⽰成⼆进制。

接下去利⽤位运算实现即可。

代码实现 模板题链接: 代码模板如下:时间复杂度O(logk)int qmi(int a,int k,int p){int res=1%p;while(k){if(k&1)res=(long long)res*a%p;a=(long long)a*a%p;k>>=1;}return res;} 值得⼀提的是,以上代码在过程中取模,是基于模运算的运算规则。

模运算有⼀些很好的性质,以下列举四条: (a + b) % p = (a % p + b % p) % p (a - b) % p = (a % p - b % p + p) % p (a * b) % p = (a % p * b % p) % p (a^b) % p = ((a % p)^b) % p⼆、快速幂求逆元乘法逆元的定义若整数 因为在模运算中,并没有除法的性质,即没有(a/b)%p≠((a%p)/(b%p))%p,⽽乘法逆元便可以帮助我们将其转化成乘法形式:a/b % m=a∗x % m。

由乘法逆元的定义我们可以推出如下结论:∵ a/b mod p = a * b-1 mod p = a/b * b * b-1 mod p∴ b * b-1≡ 1(mod p)费马⼩定理若p是⼀个质数,且整数a不是p的倍数(a与p互质),则有a p-1 ≡ 1(mod p)。

基于这个定理,我们就可以推出如下结论:∵ a p-1≡ 1(mod p)∴ a * a p-2≡ 1(mod p) 因此,结合乘法逆元的定义所得到的推论以及费马⼩定理,我们可以得到:a-1 = a p-2(mod p)。

利用快速幂进行矩阵乘法运算

利用快速幂进行矩阵乘法运算

利用快速幂进行矩阵乘法运算一、概述快速幂算法是一种数值优化技术,其基本思想是将指数直接乘到底层参数上。

由于在经典算法中必须一一相乘,而快速幂算法则可以大大减少乘法次数,从而提高算法运行效率。

这种技术也被应用在矩阵乘法运算中,称为快速幂矩阵乘法算法。

二、快速幂矩阵乘法算法介绍快速幂矩阵乘法算法是一种优化矩阵乘法运算的方法,其基本思想是通过分治算法,把两个矩阵划分为4个小矩阵,再采用快速幂算法将其相乘得到最终结果。

假设有一个n*n的矩阵A,矩阵A可以分解为4个n/2*n/2的小矩阵:A = (a11,a12,a21,a22)同理,B也可以分解为4个n/2*n/2的小矩阵:B =(b11,b12,b21,b22)用快速幂算法,将这4个小矩阵相乘得到最终结果:C = A × B = (c11,c12,c21,c22)其中:c11 = a11*b11+a12*b21c12 = a11*b12+a12*b22c21 = a21*b11+a22*b21c22 = a21*b12+a22*b22上述就是快速幂矩阵乘法算法的基本原理,由此看出,采用快速幂算法可以有效减少乘法次数,提高算法运行效率。

三、快速幂矩阵乘法算法的优化由于快速幂算法可以有效减少乘法次数,因此在矩阵乘法运算中,可以采用一些优化技术来提高算法的效率。

其一:存储矩阵的行列式在矩阵乘法运算中,由于矩阵A和矩阵B可以分解为4个小矩阵,因此可以先将这4个小矩阵的行列式存储起来,用于矩阵运算,从而可以提高算法的运行效率。

其二:采用分块乘法由于矩阵A和矩阵B的乘积可以分解为4个小矩阵,因此可以考虑将其分块,用不同的线程计算4个小矩阵的乘积,从而加速矩阵乘法的计算速度。

四、快速幂矩阵乘法算法的应用(1)经典的图像处理运算如卷积运算卷积操作其实就是矩阵运算,采用快速幂矩阵乘法算法可以有效减少乘法次数,提高运算效率。

(2)矩阵算法的实时优化经典的矩阵乘法运算在运算速度和计算负荷方面都有明显的提高,采用快速幂矩阵乘法算法可以进一步提高矩阵运算效率,这样可以更好的满足实时性要求。

矩阵快速幂基础讲解

矩阵快速幂基础讲解

矩阵快速幂基础讲解1.基础知识储备篇矩阵的相关运算会再线性代数中学到。

1.1矩阵的定义:N阶⽅阵(N阶矩阵):⾏数m与列数n相同的矩阵,如下图所⽰就是⼀个44的⽅阵:*⾏矩阵(⾏向量):只有⼀⾏的矩阵,下图就是⼀个⾏矩阵:列矩阵(列向量):只有⼀列的矩阵,下图就是⼀个列矩阵:同型矩阵:设先有矩阵A和矩阵B,矩阵A的⾏数与列数和矩阵B的相同,则矩阵A、B是同型矩阵。

单位矩阵:在矩阵的乘法中,有⼀种矩阵起着特殊的作⽤,如同数的乘法中的1,这种矩阵被称为单位矩阵.它是个⽅阵,从左上⾓到右下⾓的对⾓线(称为主对⾓线)上的元素均为1。

除此以外全都为0。

如下图所⽰是⼀个3阶的单位矩阵。

···1.2矩阵的相关运算:矩阵加法:矩阵乘法2.矩阵快速幂引⼊篇整数快速幂:为了引出矩阵的快速幂,以及说明快速幂算法的好处,我们可以先求整数的幂。

如果现在要算X^8:则 X X X X X X X X 按照寻常思路,⼀个⼀个往上⾯乘,则乘法运算进⾏7次。

(X X)(X X)(X X)(X X)这种求法,先进⾏乘法得X2,然后对X2再执⾏三次乘法,这样去计算,则乘法运算执⾏4次。

已经⽐七次要少。

所以为了快速算的整数幂,就会考虑这种结合的思想。

现在要考虑应该怎么分让计算⽐较快。

接下来计算整数快速幂。

例如:X^19次⽅。

19的⼆进制为:1 0 0 1 1 。

由(X m)*(X n) = X^(m+n)则X^19 = (X16)*(X2)*(X^1)那么怎么来求解快速幂呢。

请看下列代码:求解X^N的值。

///整数快速幂,计算x^Nint QuickPow(int x,int N){int res = x;int ans = 1;while(N){if(N&1){ans = ans * res;}res = res*res;N = N>>1;}return ans;}那么让我们来看看下⾯这段代码到底对不对:对于X^19来说:19的⼆进制为:1 0 0 1 1初始:ans = 1; res = x;则10011最后⼀位是1,所以是奇数。

矩阵乘法 精讲

矩阵乘法 精讲

• • • • • • • • • • • • • • •
Matrix mtCal(Matrix A, int k) // 求S (k) = A + A2 + A3 + … + Ak { if(k == 1) return A; Matrix B = mtPow(A, (k+1) / 2); Matrix C = mtCal(A, k / 2); if(k % 2 == 0) { return mtMul(mtAdd(mtPow(A, 0), B), C); // 如S(6) = (1 + A^3) * S(3)。 } else { return mtAdd(A, mtMul(mtAdd(A, B), C)); // 如S(7) = A + (A + A^4) * S(3) } }
利用矩阵乘法可以在om的时间里把所有操作合并为一个矩阵然后每个点与该矩阵相乘即可直接得出最终该点的位置总共耗时omn
矩阵乘法
矩阵乘法是一种高效的算法可以把一些一维递推优化到log ( n ),还可以求路径方案等,所以更是是一种应用性极强的 算法。矩阵,是线性代数中的基本概念之一。一个m×n的矩阵 就是m×n个数排成m行n列的一个数阵。由于它把许多数据紧凑 的集中到了一起,所以有时候可以简便地表示一些复杂的模型。 矩阵乘法看起来很奇怪,但实际上非常有用,应用也十分广泛。
• Output
• Output the elements of S modulo m in the same way as A is given.
• Sample Input
• • • • 224 01 11 Sample Output
• 12 • 23

快速幂取模算法详解

快速幂取模算法详解

快速幂取模算法详解转载⾃:https:///dbc_121/article/details/77646508快速幂取模的⽤途:在ACM这类竞赛中,可能会遇到指数型的数据取模问题,这个时候如果直接⽤int或者long long储存,就有可能会超出计算机整数的存取范围,⽽导致数据出错。

所以我们需要⼀种⽅法进⾏计算。

⽽这种⽅法就是我们这次要讲到的快速幂取模(简称快速幂)。

这种算法在时间和空间上都做了尽可能的优化,所以学会之后,会觉得⾮常好⽤。

快速幂取模的思路:快速幂实现的最基本的理论就是我们离散课上或者数论中学过的⼀条公式推出的引理。

引理:积的取余等于取余的积的取余。

再在这条引理的基础之上,对指数型数据进⾏拆分以及合并,从⽽得到我们⽤的快速幂算法。

本⽂我就不⽤例题讲解,直接对快速幂进⾏解析。

毕竟快速幂的算法相对简单,⽽且适⽤题型较为⼀致。

快速幂具体分析:对a^b进⾏分析。

对于当a和b较⼩是直接⽤int或者long存是没有问题的,但是当a和b⼤到⼀定程度时,这就不是暴⼒存就可以解决的问题了。

我们应该怎么去解决这个问题呢?在这⾥我们需要把注意⼒放在“⼤”字上⾯,正是由于a和b过⼤才导致的问题。

所以我们要想办法不断地减⼩a和b的规模,所谓逐个击破。

根据上⾯的那条引理,我们知道了可以把指数拆开,从这个突破⼝突破。

这⾥我们就不难想到这样⼀个算法://①a是底数,b是指数,mode是取模数,sum是记录取模的结果int sum = 1;a = a % mode;for(int i = 1; i <= b; i++){sum = sum * a;}sum = sum % c;这是直接利⽤的引理⽽写出来的代码,这只是单纯的降低的a的规模,但是这还达不到我们的要求,所以我们需要进⼀步改进算法。

(当然还可以继续降低啊的规模,即将循环中的那句换成sum = (sum * a)%mode)我们已经实现的降低a的规模,所谓我们要想着怎么降低b的规模。

很详细的快速幂算法

很详细的快速幂算法

快速幂取模算法在网站上一直没有找到有关于快速幂算法的一个详细的描述和解释,这里,我给出快速幂算法的完整解释,用的是C 语言,不同语言的读者只好换个位啦,毕竟读C 的人较多~ 所谓的快速幂,实际上是快速幂取模的缩写,简单的说,就是快速的求一个幂式的模(余)。

在程序设计过程中,经常要去求一些大数对于某个数的余数,为了得到更快、计算范围更大的算法,产生了快速幂取模算法。

[有读者反映在讲快速幂部分时有点含糊,所以在这里对本文进行了修改,作了更详细的补充,争取让更多的读者一目了然]我们先从简单的例子入手:求c a b mod = 几。

算法1.首先直接地来设计这个算法:int ans = 1;for (int i = 1;i<=b;i++){ans = ans * a;}ans = ans % c;这个算法的时间复杂度体现在for 循环中,为O (b ).这个算法存在着明显的问题,如果a 和b 过大,很容易就会溢出。

那么,我们先来看看第一个改进方案:在讲这个方案之前,要先有这样一个公式: c c a c a b b m od )m od (m od =.这个公式大家在离散数学或者数论当中应该学过,不过这里为了方便大家的阅读,还是给出证明:引理1:cc b c a c de cde c dk te tkc ce kc d tc c ab ekc b e c b dtc a d c a cc b c a c ab mod )]mod ()mod [(mod mod ))((mod ))((mod mod mod mod )]mod ()mod [(mod )(:2⨯==+++=++=+=⇒=+=⇒=⨯=证明:公式上面公式为下面公式的引理,即积的取余等于取余的积的取余。

ca c c a c c c a cc a cc a c a b b b b b b mod mod ])mod [()(mod ])mod )mod [((mod ])mod [(mod )mod (mod ===由上面公式的迭代证明:公式:证明了以上的公式以后,我们可以先让a 关于c 取余,这样可以大大减少a 的大小, 于是不用思考的进行了改进:算法2:int ans = 1;a = a % c; //加上这一句for (int i = 1;i<=b;i++){ans = ans * a;}ans = ans % c;聪明的读者应该可以想到,既然某个因子取余之后相乘再取余保持余数不变,那么新算得的ans 也可以进行取余,所以得到比较良好的改进版本。

整数快速幂(取模)、矩阵快速幂及其应用

整数快速幂(取模)、矩阵快速幂及其应用

整数快速幂(取模)、矩阵快速幂及其应⽤摘要: 本⽂主要介绍了整数快速幂、矩阵快速幂及其应⽤,以题为例重点展⽰了使⽤细节。

我们要计算⼀个整数x的n次⽅,即x^n,普通的⽅法是连乘,这⾥介绍⼀种效率⾮常⾼的计算幂运算的算法——反复平⽅法。

⾸先考虑加速幂运算的⽅法,如果n=2^k,则可以将x^n = ((x2)2)..,即只要做k次平⽅运算就可以求得x^n。

然后由此我们可以想到,先将n表⽰为2的幂次之和,即x^n = 2k1 + 2k2 + 2k3... ,那么 x^n = x2^k1 * x2^k2 * x2^k1 ...,只需在求x2^i 的同时进⾏计算就好了。

最终得到O(logn)的计算幂运算的算法。

⽐如计算x^22 = x^16 * x^4 * x^2,其中22的⼆进制数是10110,也就是需要反复平⽅3次。

代码如下:1 typedef long long ll;2 ll qpow(ll x, ll n) {3 ll res = 1;4while(n) {5if(n&1)6 res = res * x; //如果⼆进制最低位为1,则乘上x^(2^i)7 x = x * x; //将x平⽅8 n >>= 1; //n/29 }10return res;11 } 在实际应⽤中有时还需要求解x^n%mod。

代码如下:1 typedef long long ll;2 ll qpow(ll x, ll n, ll mod) {3 ll res = 1;4while(n) {5if(n&1)6 res = res * x % mod; //如果⼆进制最低位为1,则乘上x^(2^i)7 x = x * x % mod; //将x平⽅8 n >>= 1; //n/29 }10return res;11 } 看⼀道例题: 判断是否是C数,需要满⾜以下两个条件 1.不是素数. 2.对任意的1<x<n都有x^n和x同余模n. 代码如下:1 #include <cstdio>2 #include <cmath>3 typedef long long ll;45 ll qpow(ll x, ll n, ll mod) {6 ll res = 1;7while(n) {8if(n&1)9 res = res * x % mod;10 x = x * x % mod;11 n >>= 1;12 }13return res;14 }15bool isprime(ll x) {16if(x == 0 || x == 1)17return0;18 ll k = (ll)sqrt(x);19for(ll i = 2; i < k; i++) {20if(x % i == 0)21return0;22 }23return1;24 }25int main()27 ll n;28while(scanf("%lld", &n) == 1 && n != 0) {29if(isprime(n)) {30 printf("%lld is normal.\n", n);31continue;32 }33 ll i;34for(i = 2; i < n; i++) {35if(qpow(i, n, n) != i % n)36break;37 }38if(i == n)39 printf("The number %lld is a Carmichael number.\n", n);40else41 printf("%lld is normal.\n", n);42 }43return0;44 } 现在要求⼀个矩阵A的m次幂,也就是A^m,⾸先应该会两个矩阵的乘法,然后知道A^m的结果⼀定是⼀个同型矩阵,最后需要理解上⾯的整数快速幂。

矩阵快速幂和矩阵乘法

矩阵快速幂和矩阵乘法

矩阵快速幂和矩阵乘法矩阵并不是⼀个数⽽是可以表⽰⼀个⽐较复杂的模型(集合),⽽集合⾥封装着任意类型的值,⽽矩阵乘法则是⼀个⽐较重要的⼀个运算⽅式。

先说⼀下矩阵乘法的定义:矩阵乘以矩阵的时候。

这个结果是怎么算出来的?也就是说,结果矩阵第m⾏与第n列交叉位置的那个值,等于第⼀个矩阵第m⾏与第⼆个矩阵第n列,对应位置的每个值的乘积之和。

公式则是:其中c ij为A的第i⾏与B的第j列对应乘积的和,即:C ij =Σa ik*b kj(1<=i<=n,1<=j<=n,1<=k<=n)。

Example(线性⽅程式)矩阵的最初⽬的,只是为线性⽅程组提供⼀个简写形式。

附矩阵乘法的代码const int N=100;int c[N][N]; //c是最终的矩阵void multi(int a[][N],int b[][N],int n){memset(c,0,sizeof c);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) for(int k=1;k<=n;k++) c[i][j]+=a[i][k]*b[k][j];}快速幂求幂时我们常常会因结果太⼤⽽导致速度很慢,这时候我们就需要运⽤倍增的思想特殊的乘法应运⽽⽣————快速幂。

举个例⼦,如果求a10,我们需要求⼗次,⽽如果我们⽤了快速幂就可以把a10转变为⼆进制的形式从⽽加快运算速度。

⽽我们⼜知道a i=(a i/2)2因此就有如下代码总的来说就是把指数变⼩,底数变⼤,让运算次数变⼩的过程。

(感觉我就这句话写的有⽤int fastpow(int a,int i){int ans=1;//ans是最后的结果int res=a;//res就相当于上⽂中的a的i-1次⽅。

while (i>0){if (i%2==1)//因为当I是奇数的时候你就不能再把它分成2进制啦ans=ans*res;//这时候就将res乘上去res=res*res;//底数不停变⼤i=i/2;指数缩⼩}return ans;}接下来就是矩阵快速幂了。

快速幂讲解——精选推荐

快速幂讲解——精选推荐

快速幂讲解 快速幂这个东西⽐较好理解,但实现起来到不⽼好办,记了⼏次⽼是忘,今天把它系统的总结⼀下防⽌忘记。

⾸先,快速幂的⽬的就是做到快速求幂,假设我们要求a^b,按照朴素算法就是把a连乘b次,这样⼀来时间复杂度是O(b)也即是O(n)级别,快速幂能做到O(logn),快了好多好多。

它的原理如下: 假设我们要求a^b,那么其实b是可以拆成⼆进制的,该⼆进制数第i位的权为2^(i-1),例如当b==11时11=a(2^0+2^1+2^3) a 11的⼆进制是1011,11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1,因此,我们将a¹¹转化为算 a2^0*a2^1*a2^3,也就是a1*a2*a8,看出来快的多了吧原来算11次,现在算三次,但是这三项貌似不好求的样⼦....不急,下⾯会有详细解释。

由于是⼆进制,很⾃然地想到⽤位运算这个强⼤的⼯具:&和>> &运算通常⽤于⼆进制取位操作,例如⼀个数 & 1 的结果就是取⼆进制的最末位。

还可以判断奇偶x&1==0为偶,x&1==1为奇。

>>运算⽐较单纯,⼆进制去掉最后⼀位,不多说了,先放代码再解释。

1int poww(int a, int b) {2int ans = 1, base = a;3while (b != 0) {4if (b & 1 != 0)5 ans *= base;6base *= base;7 b >>= 1;8 }9return ans;10 } 代码很短,死记也可⾏,但最好还是理解⼀下吧,其实也很好理解,以b==11为例,b=>1011,⼆进制从右向左算,但乘出来的顺序是 a^(2^0)*a^(2^1)*a^(2^3),是从左向右的。

矩阵快速幂——精选推荐

矩阵快速幂——精选推荐

矩阵快速幂矩阵快速幂,就是矩阵乘法和快速幂的结合,所以在讲矩阵快速幂之前,先讲讲矩阵乘法和快速幂。

矩阵矩阵的定义什么是矩阵?由 m×n 个数 a i,j(i=1,2,⋯,m;j=1,2,⋯,n) 排成的⼀个 m ⾏ n 列的数表a1,1a1,2⋯a1,na2,1a2,2⋯a2,n⋮⋮⋱⋮a m,1a m,2⋯a m,n被称为 m ⾏ n 列矩阵,简称 m×n 矩阵。

为了表⽰这是个整体总是加⼀个括弧,并⽤⼤写字母表⽰他,计做:A=a1,1a1,2⋯a1,n a2,1a2,2⋯a2,n ⋮⋮⋱⋮a m,1a m,2⋯a m,n这个矩阵中的m×n个数被称为矩阵A的元素,简称元。

矩阵A也可被计做A m×n。

⾏矩阵(⾏向量):只有⼀⾏的矩阵。

列矩阵(列向量):只有⼀列的矩阵。

同型矩阵:两个矩阵A、B的⾏数和列数都相等单位矩阵:在矩阵乘法中起着很⼤的作⽤,相当于乘法中的1,她是个⽅阵(即⾏数和列数相同的矩阵),左上⾓到右下⾓的对⾓线(被称为主对⾓线)上的元素都是1,除此之外都是0。

如下就是⼀个4×4的单位矩阵:1000010000100001矩阵加法我们定义两个m ×n的矩阵A和B相加为:A+B=a1,1+b1,1a1,2+b1,2⋯a1,n+b1,n a2,1+b2,1a2,2+b2,2⋯a2,n+b2,n ⋮⋮⋱⋮a m,1+b m,1a m,2+b m,2⋯a m,n+b m,n注意:矩阵加法满⾜交换律和结合律只有两个同型矩阵才可以做加法矩阵乘法我们定义两个矩阵 A m×s 和 B s×n 相乘得到⼀个矩阵 C m,n,并且c i,j=a i,1b1,j+a i,2b2,j⋯+a i,s b s,j=s∑k=1a i,k b k,j并将此计做 C=AB。

注意: 矩阵乘法不满⾜交换律,但满⾜结合律和分配律。

这⾥没放图是因为放了也看不懂(逃如果还不理解的话可以看⽤代码写出来就是下⾯这个亚⼦:struct matrix{int n,m;//n是⾏数,m是列数ll e[105][105];}a;matrix mul(matrix a,matrix b){matrix ans;ans.n=a.n;ans.m=b.m;for(int i=1;i<=ans.n;i++)for(int j=1;j<=ans.m;j++)ans.e[i][j]=0;//初始化[][] []Processing math: 100%for(int i=1;i<=a.n;i++)for(int j=1;j<=b.m;j++)for(int k=1;k<=a.m;k++)ans.e[i][j]=(ans.e[i][j]+(a.e[i][k]*b.e[k][j])%mod)%mod;//矩阵乘法结果可能很⼤,所以要取模return ans;}快速幂⼀般我们求 x y 的⽅法是⼀个个乘过去,但这种⽅法太慢了。

矩阵乘法(一):基本运算

矩阵乘法(一):基本运算

矩阵乘法(⼀):基本运算矩阵,是线性代数中的基本概念之⼀。

⼀个m×n的矩阵就是m×n个数排成m⾏n列的⼀个数阵。

在计算机中,⼀个矩阵实际上就是⼀个⼆维数组。

因此,可以将矩阵定义为⼀个结构体:struct Matrix{int mat[110][110]; // 存储矩阵中各元素int row,col; // 矩阵的⼤⼩,row⾏,col列};矩阵相乘是矩阵的⼀种基本运算。

设A为m×n矩阵,B为n×k矩阵,则它们的乘积AB(有时记做A·B)是⼀个m×k矩阵。

其乘积矩阵A·B的第i⾏第j列的元素为第⼀个矩阵A第i⾏上的n个数与第⼆个矩阵B第j列上的n个数对应相乘后所得的n个乘积之和。

即:需要注意的是:只有当矩阵A的列数与矩阵B的⾏数相等时,矩阵A×B才有意义。

因此,矩阵相乘不满⾜交换律。

设A是3×4矩阵,B是4×5矩阵,A与B相乘后,A·B是3×5矩阵;但B·A根本就⽆法运算。

矩阵乘法满⾜结合律。

【例1】矩阵的乘法。

输⼊矩阵a和矩阵b的数据,输出新的矩阵c=a*b。

例如,样例输⼊4 31 2 34 5 67 8 910 11 123 57 8 9 10 114 5 6 7 81 2 3 4 5样例输出18 24 30 36 4254 69 84 99 11490 114 138 162 186126 159 192 225 258(1)编程思路。

按照矩阵乘法的定义,⽤⼀个三重循环完成运算。

(2)源程序。

#include <stdio.h>#include <string.h>struct Matrix{int mat[110][110]; // 存储矩阵中各元素int row,col; // 矩阵的⼤⼩,row⾏,col列};Matrix matMul(Matrix a ,Matrix b) // 矩阵A*B{Matrix c;c.row=a.row;c.col=b.col;memset(c.mat,0,sizeof(c.mat));int i,j,k;for (i = 0; i<=a.row ; i++)for (j=0 ;j<b.col; j++)for (k = 0 ;k<a.col;k++)c.mat[i][j] += a.mat[i][k] * b.mat[k][j];return c;}int main(){int i,j,x,y;Matrix a,b,c;scanf("%d%d",&x,&y);a.row=x;a.col=y;for (i=0;i<x;i++)for (j=0;j<y;j++)scanf("%d" ,&a.mat[i][j]);scanf("%d%d",&x,&y);b.row=x;b.col=y;for (i=0;i<x;i++)for (j=0;j<y;j++)scanf("%d" ,&b.mat[i][j]);c=matMul(a,b);for (i = 0 ;i <c.row;i++){for (j=0;j<c.col;j++)printf("%5d" ,c.mat[i][j]);printf("\n");}return 0;}在实际应⽤中,我们经常会⽤到矩阵的幂运算。

人教版数学八年级上册..幂的乘方课件精品课件PPT

人教版数学八年级上册..幂的乘方课件精品课件PPT

人教版数学八年级上册14.1.2幂的乘 方课件 人教版数学八年级上册14.1.2幂的乘 方课件

1、在困境中时刻把握好的机遇的才能 。我在 想,假 如这个 打算是 我往履 行那结 果必定 失败, 由于我 在作决 策以前 会把患 上失的 因素斟 酌患上 太多。

2、人物作为支撑影片的基本骨架,在 影片中 发挥着 不可替 代的作 用,也 是影片 的灵魂 ,阿甘 是影片 中的主 人公, 是支撑 起整个 故事的 重要人 物,也 是给人 最大启 示的人 物。

3、在生命的每一个阶段,阿甘的心中 只有一 个目标 在指引 着他, 他也只 为此而 踏实地 、不懈 地、坚 定地奋 斗,直 到这一 目标的 完成, 又或是 新的目 标的出 现。

4、让学生有个整体感知的过程。虽然 这节课 只教学 做好事 的部分 ,但是 在研读 之前我 让学生 找出风 娃娃做 的事情 ,进行 板书, 区分好 事和坏 事,这 样让学 生能了 解课文 大概的 资料。
(3)(a m )3 =_a_m___a_m___a_m__a_m__m__m =a( 3m )
(m是正整数)
人教版数学八年级上册14.1.2幂的乘 方课件
人教版数学八年级上册14.1.2幂的乘 方课件


14.1.2 幂的乘方
观察下面结论,等式左右两边的底数、指 数有什么联系?
(33)2=36
(a4)3 =a12
这个式子有
式且底数
何特点?
10444 也是幂的
形式
=1012
人教版数学八年级上册14.1.2幂的乘 方课件
人教版数学八年级上册14.1.2幂的乘 方课件
探究
14.1.2 幂的乘方

矩阵乘法矩阵快速幂最基本的矩阵模型——斐波那契数列

矩阵乘法矩阵快速幂最基本的矩阵模型——斐波那契数列

矩阵乘法矩阵快速幂最基本的矩阵模型——斐波那契数列矩阵,⼀个神奇⼜令⼈崩溃的东西,常常⽤来优化序列递推在百度百科中,矩阵的定义:在数学中,矩阵(Matrix)是⼀个按照长⽅阵列排列的复数或实数集合,最早来⾃于⽅程组的系数及常数所构成的⽅阵。

这⼀概念由19世纪英国数学家凯利⾸先提出。

好,很⾼深对吧。

那我们就更加直接地理解⼀下矩阵的实质:⼆维数组好了这个SB都会,就不解释了同⼆维数组⼀样,矩阵是⼀个'纵横排列的⼆维数据表格',它⼀般是⼀个n*m的⼆维数组,其中n*m表⽰它有n⾏m列每⼀位上的数可以⽤下标i,j来表⽰,形如这样⼀个矩阵:这⾥我们就可以⽤B[1][2]来表⽰8这个元素矩阵有加/减/乘法(有没有除法我不知道),其中加减法的限制⽐较⼤,当且仅当两个矩阵的⾏列数都相等时才能进⾏加减加减的操作也很简单,只需要按位加减即可这些都是次要的,最主要的其实是矩阵乘法我们定义矩阵乘法:设A为m*p的矩阵,B为p*n的矩阵,那么称m*n的矩阵C为矩阵A与B的乘积,记作C=AB,其中矩阵C中的第i⾏第j列元素可以表⽰为:这样我们就很轻松的得到了⼀个O(n^3)的矩阵乘法,虽然还有更快的,但⼀般来说已经⾜够矩阵乘法有以下⼏条重要性质:矩阵乘法满⾜集合律,即(AB)C=A(BC)矩阵乘法满⾜分配律,即(A+B)C=AC+BC矩阵乘法⼀般不满⾜交换律以上第三条就告诉我们,平时写两个数相乘的时候可以为所欲为,但是矩阵就完全不同了,AB!=BA很简单,结合矩阵乘法来理解下。

换句更简单的,甚⾄交换后这两个矩阵都⽆法相乘,因为他们的列数可能就不相等了然后我们⼜由于第⼀条可以得出矩阵快速幂的算法⾸先矩阵幂只有⽅阵(即⾏数等于列数的矩阵)才可以做,要不然到后⾯都乘不了了(还是因为列数不相等了)这个也很简单,我们只需要把⼀般的快速幂乘法部分改成矩阵乘法即可还是⼀句话:不要乘反了!对了,还要引出⼀个叫单位矩阵的东西,这个就好⽐⼀般乘法中的单位1⼀样。

矩阵快速幂

矩阵快速幂

[ f[n] [ f[n] [
f[n-1] f[n]
]* [ ]= f[n-1]+f[n] ]= f[n+1] ]
01 11
矩阵快速幂
例如: f(n)= a*f(n-1)+b*f(n-2) f(n)= a*f(n-1)+b*f(n-2)+c*f(n-3)
[f(n-1),f(n-2)]*[ [f(n) ,f(n-1)]
矩阵乘法
矩阵乘法
矩阵运算律 : 结合律:(AB)C=A(BC) 分配律:(A+B)C=AC+BC
C(A+B)=CA+CB
若A为m×s矩阵,B为s×n矩阵,则AB为 m×n矩阵 而BA无法进行矩阵乘法运算;即便是方阵( n×n)交换后乘得的结果也不一定相同,除 了相当特殊的,例如每个元素都是1的方阵
取模+超时---->快速幂 but 公式怎么快速幂呢?
矩阵快速幂
f[0]=0; f[1]=1; …… f[n]=f[n-1]+f[n-2]
]* [ ]= [ f[n] f[n-1]+f[n] ] [ f[n+1] f[n]+f[n+1]
f[n-1] f[n] f[n] f[n+1] 01 11
矩阵快速幂
即(a^b+8)%9+1 边计算边取模,整个过程只有乘法操作,不影响最终结果 int pow(int a,int k) //计算a^k,并最终结果对9取摸 { if(k==0) return 1; if(k==1) return a%9; if(k%2==0) return (g((a%9)*(a%9),k/2)%9); if(k%2==1) return (a%9)*(g((a%9),k-1)%9); }

矩阵乘法的快速幂

矩阵乘法的快速幂

矩阵乘法的快速幂快速幂是一种优化算法,用于求取幂运算的结果。

在数学中,我们知道,一个数的幂可以通过连续的乘法运算得到,但是当指数较大时,这种计算方式会变得十分耗时。

而快速幂算法则通过利用幂运算的一些特性,将指数的计算过程进行了优化,从而大大提高了计算效率。

在矩阵运算中,同样可以应用快速幂算法来进行优化。

矩阵乘法是一种常见的运算,它的计算复杂度为O(n^3),即矩阵乘法的计算时间与矩阵维度的立方成正比。

在实际应用中,矩阵维度往往很大,因此矩阵乘法的运算量也会相应增大。

为了提高矩阵乘法的计算效率,可以利用快速幂算法进行优化。

快速幂算法的核心思想是将指数进行二进制拆分,并利用幂运算的特性进行迭代计算。

对于矩阵乘法,我们可以将指数表示为一个二进制数,然后通过对矩阵的连续平方运算,来得到最终结果。

举例来说,假设我们有一个矩阵A,我们需要计算A的n次方。

传统的方法是通过连续的乘法运算来实现,即 A * A * A * ... * A。

而利用快速幂算法,我们可以将指数n进行二进制拆分,比如n=13可以表示为二进制数1101。

然后,我们根据二进制数的每一位进行迭代计算,每次将矩阵进行平方运算,然后根据二进制位的值来决定是否要乘上当前的矩阵。

具体的计算过程如下:1. 初始化结果矩阵为单位矩阵I,即I = [[1, 0], [0, 1]];2. 将指数n转换为二进制数,比如n=13,则二进制数为1101;3. 从二进制数的最低位开始,依次遍历每一位;4. 若当前位为1,则将结果矩阵乘以当前的矩阵A;5. 将当前的矩阵A进行平方运算,即A = A * A;6. 继续遍历下一位,直到遍历完所有位数。

通过上述步骤,我们可以得到矩阵A的n次方。

由于每次迭代只需要进行平方运算和乘法运算,因此快速幂算法的时间复杂度为O(logn),大大优化了矩阵乘法的计算效率。

需要注意的是,在实际应用中,矩阵的乘法运算可能涉及到更复杂的计算,比如矩阵的加法、减法等。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第二讲:

乘方取模和矩阵快速幂
詹海艳
一、乘方取模问题

二分思想:
a n%m=

a
n 2
%m
2
2
n为偶数
a
n 2
%m a%m
n为奇数
注:把时间复杂度从O(n)降为O(logn)了

快速幂取余: m^n % k模板 int quickpow(int m,int n,int k) { int b = 1; while (n > 0) { if (n & 1) b = (b*m)%k; n = n >> 1 ; m = (m*m)%k; } return b; }

解答:
return ans; } int main() { int n,t,s; scanf("%d",&t); while(t--) { scanf("%d",&n); s=PowerMod(n,n,10); printf("%d\n",s); } return 0; }
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<cmath> #include<string> #include<algorithm> using namespace std; #define MA 10010 int PowerMod(int a,int b,int c) { int ans=1; a=a%c; while(b>0) { if(b&1) ans =(ans*a) % c; b=b>>1; a=(a*a)%c; }
的n次
幂乘以初始矩阵
得到的结果就是

因为是2*2的据称,所以一次相乘的时间复杂度是O(2^3),总的复杂度是O(logn * 2^3 + 2*2*1)。

矩阵快速幂与斐波那契数列的关系
其实用的更多是使用矩阵快速幂,算递推式,注意是递推式,简单的如斐波那契 数列的第一亿项的结果模10000000后是多少你还能用递推式去,逐项递推吗? 当然不能,这里就可以发挥矩阵快速幂的神威了,那斐波那契数列和矩阵快速幂 能有一毛钱的关系?答案是有而且很大 斐波那契的定义是f(1)=f(2)=1; 然后f(n)=f(n-1)+f(n-2) (n>=2) 我们也可以这样定 义f(1)=f(2)=1; [f(n),f(n-1)]=[f(n-1),f(n-2)][1,1,1,0],其中[1,1,1,0] 是一个2*2的矩阵 上面一行是1,1,下面一行是1,0,这样就可以化简了写成[f(n),f(n1)]=[f(2),f(1)]*[1,1,1,0]^(n-2)

例题:HDOJ1005
A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. Given A, B, and n, you are to calculate the value of f(n). Input The input consists of multiple test cases. Each test case contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed. Output For each test case, print the value of f(n) on a single line. Sample Input 113 1 2 10 000 Sample Output 2 5
#include <cstdio> #include <string> #include <cmath> #include <iostream> using namespace std; const long long M = 1000007; const long long N = 3; long long t,b,c,f1,f2; struct Node //矩阵 { long long line,cal; long long a[N+1][N+1]; Node() { line=3,cal=3; a[0][0] = b; a[0][1] = 1; a[0][2] = 0; a[1][0] = t; a[1][1] = 0; a[1][2] = 0; a[2][0] = c; a[2][1] = 0; a[2][2] = 1; } }; Node isit(Node x,long long c) //矩阵初始化 { for(long long i=0;i<N;i++) for(long long j=0;j<N;j++) x.a[i][j]=c; return x; }

作业:
HDOJ:1060、1061、2035、1005、2068
7月19日
简单描述:[f(n),f(n-1)]=[f(n-1),f(n-2)] X
1 1
1 0
这样就可以用矩阵快速幂,快速的推出斐波那契数列的第一亿项的值了(当然是 取模的值了)是不是很神奇,类似的递推式也可以,化成这种形式,用矩阵快速 幂进行计算

矩阵快速幂模板:
Node Matlab(Node x,Node s) //矩阵乘法 { Node ans; ans.line = x.line,ans.cal = s.cal; ans=isit(ans,0); for(long long i=0;i<x.line;i++) { for(long long j=0;j<x.cal;j++) { for(long long k=0;k<s.cal;k++) { ans.a[i][j] += x.a[i][k]*s.a[k][j]; ans.a[i][j]=(ans.a[i][j]+M)%M; } } } return ans; } long long Fast_Matrax(long long n) //矩阵 快速幂 { if(n==1) return f1; n-=2; long long x=1,f=n,ok=1; Node ans,tmp,ch; ans.line = 1,ans.cal = 3; ans.a[0][0] = f2, ans.a[0][1] = f1 ,ans.a[0][2] = 1; while(n>0) { if(n%2) ans=Matlab(ans,tmp); tmp=Matlab(tmp,tmp); n/=2; } return ans.a[0][0]; } int main() { long long n,T; scanf("%lld",&T); while(T--) { scanf("%lld%lld%lld%lld%lld% lld",&f1,&f2,&t,&b,&c,&n); printf("%lld\n",Fast_Matrax(n)) ; } return 0; }

解答:(矩阵快速幂法)
#include<math.h> #include<string.h> #include<iostream> #include<stdio.h> #include<stdlib.h> #define inf 0x3f3f3f using namespace std; struct mat { int matrix[2][2]; };typedef struct mat Matrix; Matrix mul(Matrix a,Matrix b) { Matrix result; result.matrix[0][0] = ( a.matrix[0][0]*b.matrix[0][0] + a.matrix[0][1]*b.matrix[1][0] )%7; result.matrix[0][1] = ( a.matrix[0][0]*b.matrix[0][1] + a.matrix[0][1]*b.matrix[1][1] )%7; result.matrix[1][0] = ( a.matrix[1][0]*b.matrix[0][0] + a.matrix[1][1]*b.matrix[1][0] )%7; result.matrix[1][1] = ( a.matrix[1][0]*b.matrix[0][1] + a.matrix[1][1]*b.matrix[1][1] )%7; return result; } void qsm(int p,int q,int n) { Matrix c,d; c.matrix[0][0] = 1;d.matrix[0][0] = p; c.matrix[0][1] = 0;d.matrix[0][1] = q; c.matrix[1][0] = 0;d.matrix[1][0] = 1; c.matrix[1][1] = 1;d.matrix[1][1] = 0; while(n) { if(n & 1) c = mul(c,d); n>>=1; d = mul(d,d); } printf("%d\n",(c.matrix[1][0]+c.matrix[1][1])%7); } int main() { int s,p,q,n; while(scanf("%d%d%d",&p,&q,&n) && p+q+n != 0) qsm(p,q,n-1); return 0; }
相关文档
最新文档