指数(连乘)的快捷求法

原创 2015年11月17日 19:06:15
平常我们用代码求指数,一般是利用循环实现,例如

求2^10,用C语言可以写为:

int result=1;
for(i=0;i<10;i++){
    result*=2;
}
但是,当指数非常大时,用这种循环无疑会非常慢,例如
求2^10000000000(10个0),需要循环2^10000000000(10个0)次,无疑非常浪费时间,尤其在做ACM题目时,时间有限,往往无法达标。
怎么办?我们看下快速求指数(连乘)的原理。
以2^7为例:(为了方便看,把乘号省略)
2^7:2 2 2 2 2 2 2 ,总共需要6次乘法运算

2^7:2 2 2|2 2 2|2,(2^3)*(2^3) *2,而2^3需要2次连乘,因此总共需要4次乘法运算(没看懂的看接下来的注释,看懂的自觉跳过)
=====================上一步的注释===========================
2^3:2*2*2,需要2次乘法运算,通过这两次乘法运算得出2^3的结果
(2^3)*(2^3),由于2^3结果已知,因此是自乘运算(等效于result*=result;),算1次乘法运算
(2^3)*(2^3) *2,最后再乘以2,因此总共有4次乘法运算

=====================注释结束==============================

再以2^8为例:

2^2:2|2,(2^1)*(2^1),2*2一次运算求出2^2

2^4:2 2|2 2,(2^2)*(2^2),再一次自乘由2^2求出2^4

2^8:2 2 2 2|2 2 2 2 ,(2^4)*(2^4),再一次自乘由2^4求出2^8

因此快速指数需要3次乘法运算即可。

发现规律了没?
采用二分的思想,每次拿次方数除2,直到商为1终止,把余数和2分次数加起来就可以了

再以2^7为例点明规律
2^7:2 2 2|2 2 2|2,
把指数7二分(7个2相乘),7/2=3(分为两个2^3相乘),7%2=1(余1个2)
2^3:2|2|2,把3均分,3/2=1(两个2^1相乘),3%2=1(余1个2)

2^1已经不能再分(此时3/2=1,即商为1时终止),因此:
指数/2=1是划分结束标志
总的乘法运算次数=划分次数(2)+余数次数(1)

再以一道ACM题辅助理解:

描述

给你一个非零整数,让你求这个数的n次方,每次相乘的结果可以在后面使用,求至少需要多少次乘。如24:2*2=22(第一次乘),22*22=24(第二次乘),所以最少共2次;             

输入
第一行m表示有m(1<=m<=100)组测试数据;
每一组测试数据有一整数n(0<n<=10000);
输出
输出每组测试数据所需次数s;
样例输入
3
2
3
4
样例输出
1
2
2
我用的是二分的方法。每次拿次方数除2,直到商为1终止,把余数和2分次数加起来就可以了。例如:7次
原始:2 2 2 2 2 2 2 
1次:2 2 2 | 2 2 2 | 2 (分了1次,余1,第二次二分只需要取3次方,7/2=3);
2次:2 |2| 2(又分了1次,余1,此时3/2=1,商为1,不用再二分了)
则共分了2次,两次余1,则2+2=4,需要分4次。
同理8次方分3次

代码如下:
#include <stdio.h>

int main(){
<span style="white-space:pre">	</span>int length;
<span style="white-space:pre">	</span>int getnum;//输入的次方<pre name="code" class="cpp">int mul(long num){//连乘的快捷算法
    unsigned long long temp;
    if(num==1)
        return 2;
    temp=mul(num/2);//递归调用
    temp=temp*temp*((num%2)?2:1); 
    if(temp>1000000)//题目只要求后6位数 
        temp%=1000000; 
    return temp;
}

int time=0;//记录2分次数 int remainder=0;//余数不为0的次数 scanf("%d",&length); for(;length>0;length--){ scanf("%d",&getnum); while(getnum!=1){ if(getnum%2) remainder++; time++; getnum/=2; } printf("%d\n",time+remainder); time=0; remainder=0; }}

=====================================================================原理解释到这,怎么运用呢?以代码展示:
<span style="font-size:18px;">int mul(long num){//连乘的快捷算法,求2^num
    unsigned long long temp;
    if(num==1)//递归结束条件,1个2相乘,即2^1,上一个指数/2=1的结果
        return 2;
    temp=mul(num/2);//递归调用
    temp=temp*temp*((num%2)?2:1); 
    return temp;
}</span>
由于每一次都是对指数按同样原理划分,以指数/2=1结束,因此采用递归的形式
精华在于
<span style="font-size:18px;">temp=temp*temp*((num%2)?2:1); //有余数:(temp^2)*2,无余数</span><span style="font-size: 18px; font-family: Arial, Helvetica, sans-serif;">(temp^2)*1</span>
((num%2)?2:1)是对余数的判断,当num%2==1时,乘以1次余下的2,当num%2==0时,使用1,即不变

matlab 非线性方程组求法

  • 2015年12月15日 15:24
  • 166KB
  • 下载

逆序的求法C实现

  • 2012年10月21日 23:33
  • 2KB
  • 下载

3.1.2矩阵连乘问题之动态规划法(自底向上)

问题描述:给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。如何确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少 问题分析:由于矩阵乘...

C语言 框架阵的求法

  • 2010年08月25日 14:54
  • 6KB
  • 下载

最小函数依赖集的求法

  • 2011年12月21日 12:19
  • 32KB
  • 下载

【编程素质】算法-矩阵连乘问题(枚举法、备忘录法、动态规划)

1,问题给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的,i=1,2…,n-1。确定计算矩阵连乘积的计算次序,使得依此次序计算矩阵连乘积需要的数乘次数最少。输入数据为矩阵个数和每个矩阵...

矩阵分析的特征值求法

  • 2010年01月01日 16:57
  • 762KB
  • 下载

Smith(史密斯)数的求法

先看一下来自百度百科的关于史密斯数的介绍: 美国有一位数字家名叫阿尔伯特·威兰斯基,他姐夫史密斯非常喜欢研究数学,所以两人经常在一起研讨各种数学问题。有时,两人碰不到一起,就习惯性地用电话交流。...

三次样条插值函数自动求法

  • 2009年11月01日 09:49
  • 183KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:指数(连乘)的快捷求法
举报原因:
原因补充:

(最多只允许输入30个字)