快速幂 位运算 与运算 右移运算 把乘方运算转换成乘法运算 AcWing 875. 快速幂

#include

using namespace std;

typedef long long LL;

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

int main()
{
    int t;
    cin>>t;
    
    while(t--)
    {
        int a,b,p;
        cin>>a>>b>>p;
        
        cout<<qmi(a,b,p)<<endl;
    }
    
    return 0;
}

之前其实算是一知半解

但是现在感觉是比较清楚了

要是看不懂可以一遍一遍看,看不同的讲解,看视频讲解,还可以去b站搜索视频讲解,看文字题解,看算法进阶指南

快速幂算法

把乘方运算转换成乘法运算

但是不是暴力的转换,如果是暴力的转换,其实没有什么意义,因为要乘的数字太多了,时间复杂度太高了

我们知道一个十进制的数字一定可以用二进制来表示,牢牢抓住这一点,可以简化计算,在规定时间内算出答案

首先假定幂指数是2的整数次方,那么我们可以先算出 2 1 , 2 2 , 2 4 , 2 8 , 2 16 , 2 32 2^1,2^2,2^4,2^8,2^{16},2^{32} 21,22,24,28,216,232,每一次算后面的数字就是前面一个数字的平方

比如说 2 32 2^{32} 232,本来暴力计算要算322相乘,现在只需要计算5次,从 2 0 2^0 20计算到 2 32 2^{32} 232,也就是只需要计算 l o g 2 32 log_2{32} log232

假设不是2的整数次幂,那么该幂指数用二进制表示,把数位上是1的部分相乘即可,数位对应的a的数值提前预处理出来

b&1是判断该数字用二进制表示的时候最后一位是不是1

b>>=1表示去掉二进制表示的时候的最后一位数字,相当于随着循环进行,结合上面的代码,可以遍历幂指数的二进制表示的每一个数位,是从最后一个数位开始从后往前遍历

每一次a=a*a表示的是预处理a,思想是倍增原理,每一次乘a太慢,注意,这里乘的不是原来的a,而是平方之后的a,也就是每一次都是新的a,比如说最开始a==2,第一次循环,a=4,第二次循环a=16,第三次循环a=16*16

每一次计算答案都需要取模运算,防止超过数据范围,两个int数据相乘会超过数据范围,所以需要强制转换成long long

你可能感兴趣的:(#,acwing算法基础,算法,c++,数据结构)