[2015/09/03] 快速幂算法 - 大数取余

做HDOJ的2035题时遇到了这个问题,估计是脑子比较笨,看了很多都不懂,后来终于找到了一个大神写的详细解释

http://wenku.baidu.com/link?url=W3_uQ5Xi45_oeU56uZVUumrk7duKWoRXiGrOhQpx4B2SApiUIBgnUzsK-eytYD3Yq64IzJj3hERyZyhfv3DNBwmyXsVSBJKUWGVVf39gp7q


简单地提一下思路。


以求a^b mod c为例,一步步地优化算法,从而最终得到快速幂算法。原帖是用C语言,这里用Java并没有什么区别。



1.

int res = 1;  //初始化结果为1

for(int i = 1;i <= b;i++){ 

    res = res * a; 

}  //通过一个O(b)的循环,令a自乘b次

res = res % c;  //最终得到的结果再取模

这个算法非常好理解,也是最简单、用时最长的,下面进行改进。


2. 首先要引出一个公理,也是接下来一直需要的式子:

a^b mod c =  (a mod c)^b mod c

根据这个概念我们对算法进行优化:

int res = 1;

a = a % c; //加上这一句

for(int i = 1;i<=b;i++)

{

res = res * a;

}

res = res % c;

时间复杂度没变,但是相对于(1)所产生的大数来说已经减小了很多,接下来我们继续改进:

那么每次的a mod c在自乘之后成为了一个新的a,又可以%c来减小结果。


3

int res = 1; 

a = a % c; //加上这一句

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

ans = ans % c;

4.

a^b mod c = (a^2)^(b/2) mod c  偶数情况

a^b mod c = (a^2)^(b/2)*a mod c  奇数情况

令 k = (a^2) mod c,那么结果只需要求 k^(b/2) mod c即可(偶数情况),奇数情况需要再乘a


int res = 1;

a = a % c;

if(b%2==1)

    res = (res * a) mod c; //如果是奇数,要多求一步,可以提前算到res中

k = (a*a) % c; //我们取a^2而不是a

for(int i = 1;i<=b/2;i++){

    res = (res * k) % c;

}

res = res % c;

时间复杂度为b/2,为了实现最终的O(log b)时间复杂度,发现b=0时所有的迭代结束


5. 快速幂算法

int res = 1;

a = a % c;

while(b>0){

    if(b % 2 == 1)

        res = (res * a) % c;

    b = b/2;

    a = (a * a) % c;

}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值