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

合集下载

矩阵快速幂欧拉定理

矩阵快速幂欧拉定理

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

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

具体而言,将底数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
  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; }
相关文档
最新文档