算法笔记学习---快速幂

简介: 算法笔记学习---快速幂

先来看一个问题:

给定三个正整数a、b、m (a<10, b<10,1<m<10),求ab%m。

这只要学过循环就能写出来了,就像下面的代码,时间复杂度是O(b):

typedef long long LL;
LLpow(LL a , LL b , LL m)
{
    LL ans = 1;
    for(int i=0;i<b;i++)
    {
        ans = ans * a % m;
    }
    return ans;
}

代码中使用long long而不用int的原因是防止两个int型变量相乘后溢出。

接下来研究一个更进一步的问题:

给定三个正整数a、b、m (a<103, b<1018, 1<m<109),求ab%m。

对这个问题,如果还是按上面的做法显然是不行的,O(b)的复杂度连支持b< 108都已经很艰难了,更何况1018。

这里要使用快速幂的做法,它基于二分的思想,因此也常称为二分幕。快速幂基于以下事实:

①如果b是奇数,那么有ab=a * a(b-1).
②如果b是偶数,那么有ab=ab/2 * ab/2.

显然,b是奇数的情况总可以在下一步转换为 b是偶数的情况,而b是偶数的情况总可以在下一步转换为b/2的情况。这样,在log(b)级别次数的转换后,就可以把b变为0,而任何正整数的0次方都是1。

举个例子,如果需要求2^10:
①对210来说,由于幂次10为偶数,因此需要先求25,然后有210=25 * 25。
②对25来说,由于幂次5为奇数,因此需要先求24,然后有25 =2 * 24。
③对24来说,由于幂次4为偶数,因此需要先求22,然后有24=22 * 22。
④对22来说,由于幂次2为偶数,因此需要先求21,然后有22=21 * 21。
⑤对21来说,由于幂次1为奇数,因此需要先求20, 然后有21=2 * 20。
⑥20=1,然后从下往上依次回退计算即可。

这显然是递归的思想,于是可以得到快速幂的递归写法,时间复杂度为O(logb):

typedef long long LL;
//求a^b % m , 递归写法
LL binaryPow(LL a , LL b , LL m)
{
    if(b==0) return 1;       //如果b为0,那么a^0=1
    //b为奇数,转换为b-1
    if(b % 2 ==0) return a * binaryPow(a , b-1 , m) % m;
    else   //b为偶数,转换为b/2
    {
        LL mul = binaryPow(a , b/2 , m);
        return mul * mul % m;
    }
}

   上面的代码中,条件if(b %2 == 1)可以用if(b& 1)代替。这是因为b& 1进行位与操作,判断b的末位是否为1,因此当b为奇数时b&1返回1, if条件成立。这样写执行速度会快一点。

   还要注意,当b%2==0时不要返回直接返回binaryPow(a, b/2, m) binaryPow(a, b/2,m),而应当算出单个binaryPow(a, b/2, m)之后再乘起来。这是因为前者每次都会调用两个binaryPow函数,导致复杂度变成O(2^log(b)) = O(b)。例如求binaryPow(8)时, 会变成binaryPow(4) binaryPow(4),而这两个binaryPow(4)都会各自变成binaryPow(2) binaryPow(2),于是就需要求四次binaryPow(2);而每个biaryPow(2)又会变成binaryPow(1) binaryPow(1),因此最后需要求八次binaryPow(1)。

另外,针对不同的题目,可能有两个细节需要注意:
①如果初始时a有可能大于等于m,那么需要在进入函数前就让a对m取模。
②如果m为1,可以直接在函数外部特判为0,不需要进入函数来计算(因为任何正整数对1取模一定等于0)。

接下来研究一下快速幂的迭代写法。

   对ab来说,如果把b写成二进制,那么b就可以写成若干二次幂之和。例如13的二进制是1101,于是3号位、2号位、0号位就都是1,那么就可以得到13=23+22 +20=8+4+1,所以a13=a8+4+1=a8 a4 a0。

   通过上面的推导,我们发现a13可以表示成a8、a4、a0 的乘积。很容易想象,通过同样的推导,我们可以把任意的ab表示成a2k、… 、a8、a4、a2、a1中若干项的乘积,其中如果b的二进制的i号位为1,那么项a2i就被选中。于是可以得到计算ab的大致思路:令i从0到k枚举b的二进制的每一 位,如果当前位为1,那么累积a2i。注意到序列a2k、… 、a8、a4、a2、a1的前一项总是等于后一项的平方,因此具体实现的时候可以这么做:
①初始令ans等于1,用来存放累积的结果。
②判断b的二进制末尾是否为1 (即判断b& 1是否为1,也可以理解为判断b是否为奇数),如果是的话,令ans乘上a的值。
③令a平方,并将b右移一位(也可以理解为将b除以2)。
④只要b大于0,就返回②。
下面把上面的伪代码写成下面的样子,也就是快速幂的迭代写法:

//c/c++
typedef long long LL;
//求a^b % m , 迭代写法
LL binaryPow(LL a , LL b , LL m)
{
    LL ans = 1;
    while(b > 0)
    {
        if(b & 1)
        {    //如果b的二进制末尾为1(也可以写成if(b % 2))
            ans = ans * a % m;  //令ans累积上a
        }
        a = a * a % m;  //令a平方
        b >>= 1;  //将b的二进制右移1位,即b = b >> 1 或 b = b / 2
    }
    return ans;
}
#python
def qpow(a,b,mod):
    ret = 1
    while b:
        if(b&1):
             ret = ret*a % mod
        a = a*a % mod
        b>>=1
    return ret
相关文章
|
1月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
【EMNLP2024】基于多轮课程学习的大语言模型蒸馏算法 TAPIR
阿里云人工智能平台 PAI 与复旦大学王鹏教授团队合作,在自然语言处理顶级会议 EMNLP 2024 上发表论文《Distilling Instruction-following Abilities of Large Language Models with Task-aware Curriculum Planning》。
|
1月前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习(8)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
1月前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
1月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
1月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
1月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构的基本概念;算法的基本概念、特性以及时间复杂度、空间复杂度等举例说明;【含常见的报错问题及其对应的解决方法】
|
1月前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之王道第2.3章节之线性表精题汇总二(5)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
IKU达人之数据结构与算法系列学习×单双链表精题详解、数据结构、C++、排序算法、java 、动态规划 你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!