a^b

题目描述

求 a 的 b 次方对 p 取模的值。

样例

输入
3 2 7
输出
2
解释
3^2 % 7 = 9 % 7 = 2

分析

按照朴素算法就是把 a a a连乘 b b b次,这样一来时间复杂度是 O ( b ) O(b) O(b)也即是 O ( n ) O(n) O(n)级别,快速幂能做到 O ( l o g n ) O(logn) O(logn)

a b a^b ab,那么其实b是可以拆成二进制的,该二进制数第i位的权为 2 i − 1 2^{i−1} 2i1,例如当 b = = 11 b==11 b==11时, a 11 = a ( 2 0 + 2 1 + 2 3 ) a^{11}=a^{(2^0+2^1+2^3)} a11=a(20+21+23)

11 11 11的二进制是 1011 1011 1011 11 = 2 3 × 1 + 2 2 × 0 + 2 1 × 1 + 2 0 × 1 11 = 2^3×1 + 2^2×0 + 2^1×1 + 2^0×1 11=23×1+22×0+21×1+20×1,因此,我们将 a 11 a^{11} a11转化为算 a 2 0 a 2 1 a 2 3 a^{2^0}a^{2^1}a^{2^3} a20a21a23

由于是二进制,很自然地想到用位运算这个强大的工具: & 和 > > >> >> ,&运算通常用于二进制取位操作,例如一个数 & 1 的结果就是取二进制的最末位。还可以判断奇偶x&1 = = 0 ==0 ==0为偶,x&1==1为奇。 > > >> >>运算比较单纯,二进制去掉最后一位 。

代码

#include <iostream>

using namespace std;
//快速幂
 
int main(){//把b拆成二进制表示 
    int a, b, p;
    cin >> a >> b >> p;
    int res = 1 % p;
    while(b){
        if(b&1) res = res * 1ll * a % p;
        //对指数b进行二进制拆分,只有二进制位为1的位是有用的位 
        a = a * 1ll * a % p;
        b >>= 1; //把b的二进制个位去掉 
    }
    cout << res << endl;
    return 0;
}

你可能感兴趣的:(位运算)