今科网站建设费用,建设企业网站个人网上,办公室设计图片,哪里做百度网站快速幂快速幂#xff08;Fast Exponentiation#xff09;算法解决这样一个问题#xff1a;求解自然数的指数运算。计算 #xfffd;#xfffd;a b时#xff0c;按照指数定义的朴素的方法是通过连续相乘#xff1a;#xfffd;#xfffd;#xfffd;#xfffd;⋯Fast Exponentiation算法解决这样一个问题求解自然数的指数运算。计算ab时按照指数定义的朴素的方法是通过连续相乘××⋯×⏟次abb次a×a×⋯×a这种方法需要进行−1b−1 次乘法当b 很大时如109109时间复杂度()O(b) 是完全不可接受的。快速幂通过巧妙的二进制分解技术将幂运算的时间复杂度从()O(b) 优化到(log)O(logb)。考虑计算13a13将指数 13 用二进制表示131101223220208401131101223220208401因此1384018×4×0×1a13a8401a8×a4×a0×a1而8(4)2((2)2)2a8(a4)2((a2)2)2分解后的幂次很容易计算算法流程初始化结果 1从最低位开始检查指数的二进制位如果当前位为 1将当前的底数2a2x乘入结果底数不断平方不断计算0,1,2...a0,a1,a2...指数右移一位重复直到指数的最高位 1 也被遍历快速幂算法也可以从递归的角度来理解这种理解方式更加直观。{1if0(/2)2ifis even×((−1)/2)2ifis oddab⎩⎨⎧1(ab/2)2a×(a(b−1)/2)2if b0if b is evenif b is oddlong long quick_pow(long long base, long long exp) {long long res 1;while (exp) {if (exp 1) {res * base;}base * base;exp 1;}return res;}带模数版本更多的时候我们要求解的是modabmodm。这也可以用快速幂思想解决。快速幂模数版本的正确性基于模运算的分配律(×)mod[(mod)×(mod)]mod(a×b)modm[(amodm)×(bmodm)]modm因此我们可以直接对a 取模同时在算法每一步中我们都对中间结果取模这保证了最终结果的正确性同时防止数值溢出。不过我们不能直接对指数取模。指数b 必须保持原值因为mod≠modmodabmodmabmodmmodm当然既然复杂度是对数的所以b 大一些一般也无所谓。long long quick_pow(long long base, long long exp, long long mod) {long long res 1;base % mod; // 先取模防止初始base过大while (exp) {if (exp 1) {res (res * base) % mod;}base (base * base) % mod;exp 1;}return res;}不过在某些特定情况下我们可以使用欧拉定理来化简指数欧拉定理如果a 和m 互质即gcd(,)1gcd(a,m)1那么()≡1(mod)aϕ(m)≡1(modm)其中()ϕ(m) 是欧拉函数表示小于m 且与m 互质的正整数的个数。所以当a 和m 互质时我们可以将指数对()ϕ(m) 取模modmod()modabmodmabmodϕ(m)modm这在某些数学和密码学应用中很有用但不是快速幂算法的必要部分。代码略。快速幂方法的时间复杂度是(log)O(logb)循环次数等于指数的二进制位数效率极高。演示计算313mod100313mod100指数 13 1101(二进制)初始化: res 1, base 3第1轮 (最低位为1): res 1×3 3, base 3² 9第2轮 (位为0): res 3, base 9² 81第3轮 (位为1): res 3×81 243 ≡ 43, base 81² 6561 ≡ 61第4轮 (位为1): res 43×61 2623 ≡ 23结果: 3¹³ ≡ 23 (mod 100)快速乘防治溢出同样的思想也可以应用到乘法本身中。两个 32 位整数相乘范围将达到 64 位两个 64 位整数相乘范围将达到 128 位。同样大小的数无法装入正确的结果。快速乘又称龟速乘模仿快速幂的思想将乘法运算转换为加法运算。核心思路是将×a×b 看作是b 个a 相加然后利用二进制分解来优化这样就可以在中间结果下取模。对于×a×b将b 二进制分解∑0⋅2其中∈{0,1}bi0∑kbi⋅2i其中 bi∈{0,1}那么××∑0⋅2∑0⋅(⋅2)a×ba×i0∑kbi⋅2ii0∑kbi⋅(a⋅2i)typedef long long ll;// 快速乘返回 (a * b) % mod防止中间过程溢出ll quick_mul(ll a, ll b, ll mod) {ll res 0;a % mod;while (b) {if (b 1) {res (res a) % mod;}a (a a) % mod; // a 2a相当于左移一位b 1;}return res;}// 使用快速乘的快速幂ll quick_pow_safe(ll base, ll exp, ll mod) {ll res 1;base % mod;while (exp) {if (exp 1) {res quick_mul(res, base, mod); // 关键替换}base quick_mul(base, base, mod); // 关键替换exp 1;}return res;}方法 时间复杂度 空间复杂度 防溢出能力直接乘法(1)O(1)(1)O(1) 无快速乘(log)O(logn)(1)O(1) 有快速乘通过(log)O(logn) 次加法替代(1)O(1) 次乘法实际上更慢了所以也叫做“龟速乘”这属于用时间换取了数值安全性。浮点幂如果是底数浮点指数自然数那么直接应用快速幂没有任何问题。但若指数是浮点数这个问题会麻烦的多浮点数指数无法直接进行二进制位操作且误差会随着运算的拆分不断累积。相比之下浮点幂的主要思想是利用自然对数变换法来计算浮点幂⋅ln()abeb⋅ln(a)其中自然对数和指数是常见且重要的函数有快速且精确的办法来实现。常见的库如C cmath、Intel MKL、GNU Scientific Library采用此类核心思路。// 伪代码示意if (a 0.0) {if (b 0) return 0.0;if (b 0) return 1.0; // 或 NaN依标准而定return INFINITY; // 或报错}if (a 1.0) return 1.0;if (b 0.0) return 1.0;if (b 1.0) return a;result exp(b * log(a)); # 对于一般情况矩阵快速幂已知矩阵A由于矩阵乘法满足结合律指数为自然数时仍可以利用快速幂思想求解An。这最其深刻、最实用的扩展之一。它将快速幂的核心理念从标量运算成功迁移到了线性代数领域。{if0(/2)2ifis even×((−1)/2)2ifis oddAn⎩⎨⎧I(An/2)2A×(A(n−1)/2)2if n0if n is evenif n is oddtypedef vectorvectorlong long Matrix;Matrix matrixMultiply(const Matrix A, const Matrix B, long long mod) {int n A.size();Matrix C(n, vectorlong long(n, 0));for (int i 0; i n; i) {for (int j 0; j n; j) {for (int k 0; k n; k) {C[i][j] (C[i][j] A[i][k] * B[k][j]) % mod;}}}return C;}Matrix matrixPow(Matrix base, long long exp, long long mod) {int n base.size();// 初始化单位矩阵Matrix res(n, vectorlong long(n, 0));for (int i 0; i n; i) {res[i][i] 1;}while (exp 0) {if (exp 1) {res matrixMultiply(res, base, mod);}base matrixMultiply(base, base, mod);exp 1;}return res;}经典案例斐波那契数列的矩阵解法斐波那契数列的递推关系()(−1)(−2)F(n)F(n−1)F(n−2)可以表示为矩阵形式[()(−1)][1110]×[(−1)(−2)][F(n)F(n−1)][1110]×[F(n−1)F(n−2)]递推得到[()(−1)][1110]−1×[(1)(0)][F(n)F(n−1)][1110]n−1×[F(1)F(0)]由于我们可以快速计算矩阵的幂我们就绕过了斐波那契数列的定义使用对数次矩阵乘法的时间直接计算出了某一项。long long fibonacci_matrix(long long n, long long mod) {if (n 0) return 0;if (n 1) return 1;Matrix base {{1, 1}, {1, 0}};Matrix result matrixPow(base, n - 1, mod);return result[0][0]; // F(n)}更一般的对于 k 阶线性递推1−12−2⋯−anc1an−1c2an−2⋯ckan−k