指数(连乘)的快捷求法

原创 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,即不变

关于二叉树遍历的快捷思考方法

二叉树遍历有前中后三种方法 前序 : 根>左>右 中序 : 左>根>右 后序 : 左>右>根 有两个题目 类似的方法可以通用 已知一棵二叉树,如果前序遍历的节点顺序是:ADCEFGHB,中序遍...
  • WindSwordNeverRegret
  • WindSwordNeverRegret
  • 2017年09月19日 15:15
  • 174

乘法逆元的快捷求法

不说了,上代码 int[] inv = new int[MAXN]; inv[1] = 1; for (int i = 2; i
  • x920405451x
  • x920405451x
  • 2015年03月07日 22:36
  • 266

SQL 聚合 连乘

sql 聚合连乘
  • walkbob
  • walkbob
  • 2015年05月05日 21:17
  • 1914

CSDN markdown 编辑器 第四篇 LaTex语法

Latex是为了写数学公式的。嗯…但实际这种语言的作用是为了排版的。数学公式只是他的附加属性。但是markdown引入这个完全是为了写公式。其他的Latex语法不支持。CSDN markdown语法支...
  • cctt_1
  • cctt_1
  • 2015年03月14日 23:31
  • 2420

求阶乘与多整数连乘问题

1. 求阶乘问题 对给定的 n(n   分析:因为要求的整数可能大大超出一般的整数的位数,所以应使用一维数组存储长整数,数组中的每个元素只存储长整数的一位数字。如有 m 位长整数 num,则用数组 ...
  • huanfengyun
  • huanfengyun
  • 2013年09月01日 21:20
  • 1436

动态规划之最优矩阵连乘

最优矩阵连乘 问题描述: 一个n*m矩阵由n行m列共n*m个数排列而成。两个矩阵A和B可以相乘当且仅当A的列数等于B的行数。一个N*M的矩阵乘以一个M*P的矩阵等于一个N*P的矩阵,运算量为nmp...
  • zhaochengyuan
  • zhaochengyuan
  • 2012年08月14日 10:30
  • 2260

计算器添加连乘连除功能

m_Operation[i]存储的是运算符,1+ 2- 3* 4/,   m_number[i]存储的是操作数,代码如下,如何实现连乘连除功能? void CCalculatorDlg::cal()...
  • u012187684
  • u012187684
  • 2014年01月05日 11:39
  • 667

读入一个自然数,将n分解为质因子连乘的形式输出(筛法)

为了提高速度,采用筛法来求质因子: #include #include #include #include using namespace std; int main () { in...
  • qsort_
  • qsort_
  • 2016年07月13日 21:21
  • 1123

机器学习中的损失函数分析与比较

损失函数(loss function)是用来估量你模型的预测值f(x)与真实值Y的不一致程度,它是一个非负实值函数,通常使用L(Y, f(x))来表示,损失函数越小,模型的鲁棒性就越好。损失函数是经验...
  • laobai1015
  • laobai1015
  • 2017年09月21日 22:02
  • 1147

KMP的next数组求法详解

近几天学习kmp算法,在next数组求解上受苦颇深,看了不少博客,感觉写得都不够清晰,所以想按照自己理解的过程来尝试写一下,也便于以后温习。...
  • to_be_better
  • to_be_better
  • 2015年10月13日 00:51
  • 3780
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:指数(连乘)的快捷求法
举报原因:
原因补充:

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