快速幂

侵删,源解析博主博客

 

让计算机很快地求出a^bab

暴力相乘的话,电脑要计算 bb 次。用快速幂,计算次数在 log_2(b)log2​(b) 级别,很实用。

原理 I

(1)如果将 aa 自乘一次,就会变成 a^2a2 。再把 a^2a2 自乘一次就会变成 a^4a4 。然后是 a^8a8…… 自乘 nn 次的结果是 a^{2^{n}}a2n 。对吧……

(2)a^xa^y = a^{x+y}axay=ax+y,这个容易。

(3)将 bb 转化为二进制观看一下:

比如 b = (11)_{10}b=(11)10​ 就是 (1011)_{2}(1011)2​ 。从左到右,这些 11 分别代表十进制的 8,2,18,2,1。可以说 a^{11} = a^8 × a^2 × a^1a11=a8×a2×a1。

为什么要这样表示?因为在快速幂的过程中,我们会把 aa 自乘为 a^2a2,然后 a^2a2 自乘为 a^4a4……像上面第一条说的。



过程会是这样:

(好长,可以不看,如果要阅读下面的模拟过程的话,要慢慢地看噢)

·假设我们拿到了 aa,并且 b = 11b=11。想求 a^{11}a11,但是又不想乘11次,有点慢。

·以电脑视角稍稍观察一下 b = 11b=11,二进制下是 b = 1011b=1011。

·制作一个 basebase。现在 base = abase=a,表示的是,a^1 = aa1=a。待会 basebase 会变的。

·制作一个 ansans,初值 11,准备用来做答案。


while(b > 0)
{

·循环一。看,b(二进制)的最后一位是 1 吗? 是的。这代表 a^{11} = a^8 × a^2 × a^1a11=a8×a2×a1 中的“ × a^1×a1 ”存在。所以 ans *= base    

if(b & 1)
    ans *= base;

/*关于 b & 1:
“&”美名曰“按位与”。
x & y 是二进制 x 和 y 的每一位分别进行“与运算”的结果。
与运算,即两者都为 1 时才会返回 1,否则返回 0。
那么 b & 1

          二进制
b     =    1011
1     =    0001
b&1   =    0001

因为 1(二进制)的前面几位全部都是 0,
所以只有 b 二进制最后一位是 1 时,b & 1 才会返回 1。
挺巧妙的,并且很快。)*/

·然后 base 努力上升,他通过自乘一次,使自己变成 a^2。

base *= base;

同时

b >>= 1;

它把(二进制的)自己每一位都往右移动了。原来的最后第二位,变成了最后第一位!b = (101)2​。

}

·循环二,再看看 b,最后一位还是 1。这说明有“ × a^2 ”,ans∗=base。

·base 继续努力,通过 base *= base让自己变成了 a^4。然后 b 也右移 一位。b=10。


·循环三,可是 b 的最后一位不再是 1 了,说明不存在“ × a^4 ”。base 自我升华,达到了 a^8。且 b >>= 1。这一步中,答案没有增加,可是毕竟 b > 0,还有希望。


·循环四,b 的最后一位是 1,这说明“ ×a^8 ”的存在。ans *= base。由于 b 再右移一位就是 0 了,循环结束。



总的来说,如果 b 在二进制上的某一位是 1,我们就把答案乘上对应的 a^{2^{n}}。不懂的话,请结合代码理解~

实现

int quickPower(int a, int b)//是求a的b次方
{
    int ans = 1, base = a;//ans为答案,base为a^(2^n)
    while(b > 0)//b是一个变化的二进制数,如果还没有用完
    {
        if(b & 1)//&是位运算,b&1表示b在二进制下最后一位是不是1,如果是:
            ans *= base;//把ans乘上对应的a^(2^n)

        base *= base;//base自乘,由a^(2^n)变成a^(2^(n+1))
        b >>= 1;//位运算,b右移一位,如101变成10(把最右边的1移掉了),10010变成1001。现在b在二进制下最后一位是刚刚的倒数第二位。结合上面b & 1食用更佳
    }
    return ans;
}

 


有很多时候我们使用快速幂是为了进行取模运算:

int quickPower(int a,int b,int m)
{
	int ans=1,base=a;
	while(b>0)
	{
		if(b & 1)//与 b mod 2 == 1等效,也就是奇数
		{
			ans *= base;
			ans %= m;	
		}
		base *= base;
		base %= m;
		b >>= 1;	//与 b/=2 等效 
	}	
	return ans;
} 

这样就保证了每次都是先乘再取模

期末大作业基于python的足球运动员数据分析源码+数据集(高分项目),个人经导师指导并认可通过的高分设计项目,评审分98分,项目中的源码都是经过本地编译过可运行的,都经过严格调试,确保可以运行!主要针对计算机相关专业的正在做大作业、毕业设计的学生和需要项目实战练习的学习者,资源项目的难度比较适中,内容都是经过助教老师审定过的能够满足学习、使用需求,如果有需要的话可以放心下载使用。 期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于python的足球运动员数据分析源码+数据集(高分项目)期末大作业基于pyth
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值