接触ACM没几天,向各路大神求教,听说ACM主要是研究算法,所以便开始了苦逼的算法学习之路。话不多说,RT所示,学习快速求幂。

在头文件<math.h>或是<cmath>中,double pow( double x, double y );函数是用来快速求x^y,于是便从pow函数来说起,以下大体上是pow的函数代码:

  1. int pow(int x, int n)
  2. {
  3. int num = 1;
  4. while (n != 0){
  5. num = num *x;
  6. n = n -1;
  7. }
  8. return num;
  9. }

通过以上程序,2^5 = 2*2*2*2*2的流程中一共进行了4次乘法。试想若是大数2^99999999.......,这样循环的算下来肯定要计算到猴年马月。那么我们有什么办法可以简化我们的幂指运算呢?

分析数据

2^4=2^2 * 2^2;

2^5=2^2 * 2^2 * 2

2^6=2^3 * 2^3

2^7=2^3 * 2^3 * 2

……

x^n = x^(n/2) * x^(n/2) (n为偶数)

x^n = x^(n/2) * x^(n/2) * n (n为奇数)

显然这种算法分析利用分治思想(divide and conquer)。通过这种方式,我们可以根据通项公式写出递归函数求分制幂指运算的函数代码:

  1. int DC_pow(int x, int n)
  2. {
  3. if (n==1) return x;
  4. if (n==0) return 1;
  5. else if (n & 1)  return DC_pow(x,n/2)*DC_pow(x, n/2)*x;      //  对应公式x^(n/2) * x^(n/2) * n
  6. else             return DC_pow(x,n/2)*DC_pow(x, n/2);        //  对应公式x^(n/2) * x^(n/2)
  7. }

由此我们以分治思想,减少了运算量。接下来,我们研究此递归代码的一些细节。对于n/2,我们在二进制位运算中还有其他的处理方式,倘若一个数是二进制数,只要我们将该数右移一位(x>>1),即可对其真值除以2。也许你又会想,DG想表述的是什么意思,即使我把代码中的n/2换成n>>1运算量有没有改变,到底意义何在呢?我们从一个例子引出:

♢问题:请求出3^999=?(问题目的在于感受不同求解方法的复杂程度)

分析:我们先调用最最基本的方式进行求解,即为求:3 * 3 * …… * 3(999个3),这样一共要进行998次乘法运算。这种方法显然是太麻烦,反复的递归,计算机心里定会默念“我靠,坑爹啊!”

接下来,我们使用简单分制思想来做此题,这样就可以大大简少运算次数,使得计算次数仅为9次。但是,如果你也在学习ACM的话,你会懂得递归做法运行速度之慢。即使递归函数通俗易懂,即使写法简单,但是并不推荐。你若不信,我给大家举一个简单的例子:

利用欧几里德算法(辗转相除法)计算两数的gcd(最大公约数)

递归形式:

  1. int gcd(int a,int b)
  2. {
  3. if(a == 0) return b;
  4. else return b == 0?a:gcd(b,a%b);
  5. }

非递归形式:

  1. int gcd(int a,int b)
  2. {
  3. int c;
  4. if(a == 0) return b;
  5. while(b!=0) c = b,b = a % b,a = c;
  6. return a;
  7. }

以上利用相同的思想进行求解a,b的gcd,但是效率有很大偏差,大家可以尝试。

那么,还有什么方法来求解这个问题呢,接下来便是经典的快速求幂法。我们将3^999进行分解,即为: (3 ^ 512) * (3 ^ 256) * (3 ^ 128) * (3 ^ 64) * (3 ^ 32) * (3 ^ 4) * (3 ^ 2) * 3。这时候,我们可以整理出3的指数部分形式:2^9+2^8+2^7+2^6+2^2+2^1+2^0。然后,我们再把999转换成2进制为1111100111,2进制的转换作为指数位置的数。由此,我们同样的利用了分治思想,将指数分成了2的n次方和的形式。配合上右移运算,我们只要将其二进制数与1做与运算,为真则将此位上的2^n次方加入,为假则不加入。下面放出代码:

  1. int spow(int x, int n)
  2. {
  3. int result = 1;
  4. while (n > 0)
  5. {
  6. if (n & 1)   result *= x;
  7. x *= x;
  8. n >>= 1;        //n=n/2
  9. }
  10. return result;
  11. }

以上便是全部内容,第一次发文,多有错误。多多包含。

学习本块知识参考过的博文:

http://blog.csdn.net/zhizichina/article/details/7573342

http://blog.csdn.net/hkdgjqr/article/details/5381028

关于快速求幂的ACM题集:

HDU1575、HDU1852、HDU2817、HDU2035.

快速求幂(Quick Exponentiation)的更多相关文章

  1. NYOJ--102--次方求模(快速求幂取模)

    次方求模 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 求a的b次方对c取余的值   输入 第一行输入一个整数n表示测试数据的组数(n<100)每组测试只有一 ...

  2. HDU 2035 人见人爱A^B(二分求幂,快速求幂)

    题意:求A的B次方的后三位数字 思路1:常规求幂,直接取余求解 代码: #include<iostream> #include<cstdio> using namespace ...

  3. Quick Pow: 如何快速求幂

    今天讲个有趣的算法:如何快速求 \(n^m\),其中 n 和 m 都是整数. 为方便起见,此处假设 m >= 0,对于 m < 0 的情况,求出 \(n^{|m|}\) 后再取倒数即可. ...

  4. ahjesus js 快速求幂

    /* 快速幂计算,传统计算方式如果幂次是100就要循环100遍求值 快速幂计算只需要循环7次即可 求x的y次方 x^y可以做如下分解 把y转换为2进制,设第n位的值为i,计算第n位的权为x^(2^(n ...

  5. NYOJ-127 快速求幂,最小生成树

    #include"iostream" using namespace std; int kuaisuqiumo(int a,int b,int c){ ; a = a % c; ) ...

  6. hdu 1005 Number Sequence(矩阵连乘+二分快速求幂)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=1005 代码: #include<iostream> #include<stdio.h&g ...

  7. 【板子】gcd、exgcd、乘法逆元、快速幂、快速乘、筛素数、快速求逆元、组合数

    1.gcd int gcd(int a,int b){ return b?gcd(b,a%b):a; } 2.扩展gcd )extend great common divisor ll exgcd(l ...

  8. 九度OJ 1085 求root(N, k) -- 二分求幂及快速幂取模

    题目地址:http://ac.jobdu.com/problem.php?pid=1085 题目描述: N<k时,root(N,k) = N,否则,root(N,k) = root(N',k). ...

  9. 二分求幂/快速幂取模运算——root(N,k)

    二分求幂 int getMi(int a,int b) { ; ) { //当二进制位k位为1时,需要累乘a的2^k次方,然后用ans保存 == ) { ans *= a; } a *= a; b / ...

随机推荐

  1. 用CSS3实现带小三角形的div框(不用图片)

    现在看到了很多带小三角形的方框,如微信.Mac版的QQ.QQ空间的时间轴等等,在聊天或者是发表的状态的内容外面都有一个带小三角形的矩形框包围着,感觉看着很不错,于是决定亲自动手写一个,我上次用的是偏移 ...

  2. My.Ioc 代码示例——避免循环依赖

    本文的目的在于通过一些示例,向大家说明 My.Ioc 支持哪些类型的依赖关系.也就是说,如何设计对象不会导致循环依赖. 在 Ioc 世界中,循环依赖是一个顽敌.这不仅因为它会导致 Ioc 容器抛出异常 ...

  3. 从Select语句看Oracle查询原理(了解Oracle的查询机制)

    第一步:客户端把语句发给服务器端执行 当我们在客户端执行select语句时,客户端会把这条SQL语句发送给服务器端,让服务器端的进程来处理这语句.也就是说,Oracle客户端是不会做任何的操作,他的主 ...

  4. How do I size a UITextView to its content?

    UITextView 自适应高度,搬来一篇stack上的:   Is there a good way to adjust the size of a UITextView to conform to ...

  5. ThinkPHP 的CURD 基本操作

    说起CURD,懂点SQL的人都知道,就是增删改查,做业务系统的时候,往往离不开这CURD,最近也是刚刚接触ThinkPHP,ThinkPHP的灵活性是比原生PHP好用的多,下面我就简单的介绍一下我的学 ...

  6. 8.模板方法模式-[Head First 设计模式]

    模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤. 要点: “模板方法”定义了算法的步骤,把这些步骤的实现延 ...

  7. protocol buffer VS 2013编译出错

    protocol buffer 在VS2013编译会出现以下错误. 解决办法 把宏加上, 问题解决. 注: 该错误只出现在Debug版本.

  8. VS2012 ActiveX控件_D接口添加方法事项

    自己写的是Clock控件,所以控件的接口是_DClock 使用向导添加方法后,会在紫色区域自动生成红色代码:(添加Hello方法) dispinterface _DClock { properties ...

  9. (转载)小课堂UI-有关配色的一个小技巧

  10. C#防SQL注入代码的实现方法

    对于网站的安全性,是每个网站开发者和运营者最关心的问题.网站一旦出现漏洞,那势必将造成很大的损失.为了提高网站的安全性,首先网站要防注入,最重要的是服务器的安全设施要做到位. 下面说下网站防注入的几点 ...