码迷,mamicode.com
首页 > 其他好文 > 详细

整数求幂

时间:2015-08-03 20:45:18      阅读:137      评论:0      收藏:0      [点我收藏+]

标签:

问题描述:求一个整数的n次幂,对m取余。

思路一:简单循环

 1 int Pow(int num, int n, int m)
 2 {
 3      int res = 1;
 4 
 5      while (n--) {
 6          res *= num;
 7      }
 8 
 9      return res % m;
10 }

以上代码有个隐患,当n足够大的时候,res会溢出,因此需要优化。

有这样一个公理:两个数的积对另一个数取余,等于这两个数分别对第三个数取余的乘积再对第三个数取余。也就是a*b%c = (a%c)*(b%c)%c

根据以上公理,可以对上面的代码进行优化:

 1 int Pow(int num, int n, int m)
 2 {
 3      int res = 1;
 4 
 5      while (n--) {
 6          res *= num;
 7          res %= m; // 增加的代码
 8      }
 9 
10      return res % m;
11 }

思路二:二分求幂

思路一的时间复杂度为O(n),我们想更快一点,就需要再次优化。

我们知道,a^n = a^(n/2) * a^(n/2) (n为偶数),a^n = a^(n/2) * a^(n/2) * a (n为奇数)

因此,如果要求a^n,只需要求得a^(n/2),根据此理论,可写出如下代码,可将时间复杂度优化为O(logn):

 1 int Pow(int num, int n, int m)
 2 {
 3      if (n == 1) {
 4          return num % m;
 5      }
 6 
 7      int tmp = Pow(num, n/2, m);
 8      if (n % 2 == 0) // n为偶数
 9      {
10          return (tmp * tmp) % m;
11      }
12      else {               // n为奇数
13          return (tmp * tmp * num) % m;
14      }
15 }

思路三:位操作

思路二中,我们采用了递归求a^(n/2),成功将时间复杂度优化到O(logn),但是递归求解会产生很多函数调用,使得效率不是看上去的那么高,我们一般优化递归的做法是将递归写为递推。

将n写为二进制,以n=11为例:a^n = a^11 = a^(2^0 + 2^1 + 2^3)

这样,根据以上推理,可将思路二中的递归写为递推:

 1 int Pow(int num, int n, int m)
 2 {
 3     int res = 1;
 4 
 5     // 把n的二进制数从低位到高位遍历,如果为1,则乘以num,
 6     // 每循环一次,num变为之前的平方,n变为之前的一半
 7     while (n) {
 8     // 二进制的最后一位为1,是原始n的第几个1,就乘以num^(2的几次幂)
 9         if (n & 1 == 1) {
10             res *= (num % m);
11         }
12         num *= num;
13         n >>= 1;
14     }
15 
16     return res % m;
17 }

 

整数求幂

标签:

原文地址:http://www.cnblogs.com/mhscn/p/4700151.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!