快速幂问题

所谓的快速幂,实际上是快速幂取模的缩写

首先,最基本的办法是:

int ans = 1;
for(int i=1;i<=b;i++){
	ans =ans*a;
}
ans =ans%c;  //ans是对answer的缩写 

但是如果a很大,那么a^b的结果就容易非常大,所以在求之前可以先对a做一个变化 如下:

int ans = 1;
a =a%c; //加上这一句 
for(int i=1;i<=b;i++){
	ans =ans*a;
}
ans =ans%c;  

加上那一句之后,求出来的答案是不会变得,,可以举个数字体味一下哦!

按照上面的思路,我们还可以在别的地方再取一次余哦,让过程中的数字尽可能地小:

int ans = 1;
a =a%c; //加上这一句 
for(int i=1;i<=b;i++){
	ans =(ans*a)%c; //这里再次取了一次余 
}
ans =ans%c;  

当当当当~~~~~经过上面,我们终于可以用快速幂来求解了:

首先,快速幂的理论基础:

快速幂的过程是快速求出a^b的过程,算到最后ans还是要%c的:

快速求出a^b:

1、当b为偶数时,a^b可以转化为(a^2)的(b/2)次方

2、当b为奇数时,a^b可以转化为(a^2)的(b/2)次方 再乘 a     //比偶数多一个乘a,可以放到最前面乘上

证明巴拉巴拉的我就不证了,可以带个数字体会一下这个过程哦!

看代码:

int ans = 1;
a =a%c; // a在此时%c是为了简化数字 
if(b%2==1)   	ans = (ans*a)%c;  //如果是基数,要求多一步,可以提前算到ans中 ,这里%c也是为了简化数字 
k=(a*a)%c; //取a^2  //k在此时%c是为了简化数字 
for(int i=1;i<=b/2;i++){
	ans =(ans*k)%c;
}
ans =ans %c;  //在求出a^b的最后不要忘记%c哦

我们可以看到,我们把时间复杂度变成了O(b/2).当然,这样子治标不治本。但我们可以看到,当我们令k = (a * a) mod c时,状态已经发生了变化,我们把最终(a^b)%c转化成了【(a^2)%c的b/2】%c,所以我们发现这个过程是可以迭代下去的。当然,对于奇数的情形会多出一项乘a的过程 ,这里像上面一样加在开始的地方ans = (ans * a) % c;就可以了。形如上式的迭代下去后,当b=0时,所有的因子都已经相乘,算法结束。于是便可以在O(log b)的时间内完成了。于是,有了最终的算法:快速幂算法。



int ans =1;
a=a%c;   
while(b>0){
	if(b%2==1) 	ans = (ans*a)%c;
	b = b/2;
	a = (a*a)%c;
}   //这里我不太懂哎,,最后为什么没有在%c 但是既然是一个简化的过程,过程中应该已经省的很多了吧

把上面的代码结构化,也就是写成函数

int PowerMod(int a,int b,int c){
	int ans =1;
	a = a%c;
	while(b>0){
	if(b%2==1) 	ans = (ans*a)%c;
	b = b/2;
	a = (a*a)%c;
} 
return ans;
}

本算法的时间复杂度为O(logb),能在几乎所有的程序设计(竞赛)过程中通过,是目前最常用的算法之一。

 

扩展:

有关于快速幂的算法的推导,还可以从另一个角度来想。

=? 求解这个问题,我们也可以从进制转换来考虑:

将10进制的b转化成2进制的表达式:

那么,实际上,.

 

所以

 

注意此处的要么为0,要么为1,如果某一项,那么这一项就是1,这个对应了上面算法过程中b是偶数的情况,为1对应了b是奇数的情况[不要搞反了,读者自己好好分析,可以联系10进制转2进制的方法],我们从依次乘到。对于每一项的计算,计算后一项的结果时用前一项的结果的平方取余。对于要求的结果而言,为时ans不用把它乘起来,[因为这一项值为1],为1项时要乘以此项再取余。这个算法和上面的算法在本质上是一样的,读者可以自行分析,这里我说不多说了,希望本文有助于读者掌握快速幂算法的知识点,当然,要真正的掌握,不多练习是不行的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值