a^b (快速幂板子)

题面:a^b
快速幂思想:

每个正整数都可以唯一表示为若干指数不重复的 2 2 2 的次幂的和。
如果 b b b 在二进制表示下有 k k k 位,其中第 i ( 0 ≤ i < k ) i(0\leq i<k) i(0i<k) 位的数字是 c i c_i ci,那么有:
b = c k − 1 2 k − 1 + c k − 2 2 k − 2 + . . . + c 0 2 0 b=c_{k-1}2^{k-1} + c_{k-2}2^{k-2} +...+c_02^0 b=ck12k1+ck22k2+...+c020
所以: a b = a c k − 1 2 k − 1 ∗ a c k − 2 2 k − 2 ∗ . . . ∗ a c 0 2 0 a^b=a^{c_{k-1}2^{k-1}}*a^{c_{k-2}2^{k-2}}*...*a^{c_{0}2^{0}} ab=ack12k1ack22k2...ac020
因为 k = ⌈ l o g 2 ( b + 1 ) ⌉ k=\lceil log_2(b+1)\rceil k=log2(b+1),所以上式乘积项的数量是小于等于 ⌈ l o g 2 ( b + 1 ) ⌉ \lceil log_2(b+1)\rceil log2(b+1) 个的。
又有: a 2 i = ( a 2 i − 1 ) 2 a^{2^i}=(a^{2^{i-1}})^2 a2i=(a2i1)2
所以,可以通过 k k k 次递推就求出每一个乘积项。
c i = 1 c_i=1 ci=1, 即当 b b b 二进制的第 i i i 项不为 0 0 0 ,且乘积项不为 1 1 1 时,把该乘积项累乘到 a n s ans ans 中。
整个算法的时间复杂度为 O ( l o g 2 b ) O(log_2b) O(log2b).

代码如下:
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

int qmi(int a, int b, int mod)
{
    int ans = 1 % mod;
    while(b)
    {
        if(b & 1)   ans = (LL)ans * a % mod;
        a = (LL)a * a % mod;
        b >>= 1;
    }
    return ans;
}

int main()
{
    int a, b, p;
    cin >> a >> b >> p;
    cout << qmi(a, b, p) << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值