【复习】快速幂算法详解

快速幂算法
就是求一个高精度幂次取余时的一个快速算法
比如我们要求 a b a^b ab%m的时候
应用于快速幂算法 也就是将O(n)转化为O(logn)的算法
他的原理就是:

2 5 2^5 25 = 2 ∗ 2 ∗ 2 ∗ 2 ∗ 2 2*2*2*2*2 22222 = 2 101 2^{101} 2101 = 2 1 ∗ 2 4 2^1 * 2^4 2124

相当于我们只需要遍历幂次的二进制位的长度就可以了
我们知道任意数x的二进制位长度是log2(x)
这样大大提升了求幂的效率

可是这样运算容易导致数据溢出
如何保证运算不超出数据范围还能正确求余呢?
我们需要借助同余定理 解决在这个求幂的运算过程中所产生的高精度问题
2 5 2^5 25%m

同余定理 就是给你定一个正整数m(m>1) 如果两个整数 a 和b 满足 a-b能够被m整除 则(a-b)/m
得到一个整数 则称a,b对模m同余

同余定理两个应用是
(a+b)%m = (a%m+b%m)%m
( a ∗ b a * b ab)%m = (a%m ∗ * b%m)%m

以上两条等式可以分别证明

这两条性质 可以应用在高精度运算中

实际上高精度就是说参与运算的数据和运算结果的范围, 超出标准数据类型能表示的数据大小范围的运算。
这个时候,如果要得到正确的计算结果,显然不能依靠普通方法实现了。 而要在普通运算原理的基础上,加以辅助算法来实现超大数据的计算。
例如:求两个100位的数据的和,或者计算两个100位的数字乘积。这时就要用到高精度算法了。

下面我们来看下代码

typedef long long ll;
ll quickpow(ll a,ll b,ll m){
    ll ans = 1;
    while(b){
        if(b%2)ans*=a;
        a*=a,a%=m;//套括号取模
        ans%=m;//套括号取模
        b>>=1;
    }
    return ans%m;//套括号取模
}

以上代码如果用表达式表达出来的话 就是

(( a n s ∗ a ans*a ansa) % m ∗ ( a ∗ a ) * ( a * a ) (aa) % m ∗ ( a ∗ a ) * ( a * a ) (aa) % m ) % m = 1 ∗ 2 5 1 *2^5 125 %m
这个完全就是我们上面写的那个同余定理的应用中对高精度取余的处理方式
那么也就是 ( ( 1 ∗ 2 ) ∗ ( 2 ∗ 2 ) ∗ ( 2 ∗ 2 ) ) ((1*2)*(2*2)*(2*2)) ((12)(22)(22))%m = [ ( 1 ∗ 2 ) [(1*2) [(12)%m ∗ ( ( 2 ∗ 2 ) * (( 2*2) ((22)%m ∗ ( 2 ∗ 2 ) *(2*2) (22)%m ) ) )%m ] ] ]%m
所以在这个过程中既不会低效 也不会导致数据溢出

这就是快速幂算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值