小白详细讲解快速幂--杭电oj2035-A^B
2015-11-30 23:20
471 查看
[align=left]Problem Description[/align]
求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”
Input
输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。
Output
对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。
简单的说这题就是要求高次幂,有两种方法可以实现。
第一总比较土鳖,每次乘完对1000取余也可以过。
我要讲的是第二种听起来很高大上的方法——快速幂。为什么叫快速幂呢?因为用它求幂非常快,对于x^n,复杂度为O(logn),是不是很吊!快速幂的原理是把幂分解,把一个很大的幂分解成较小的几部分。例如:
11的二进制是1011
11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1
因此,我们将a¹¹转化为
即把n化为2进制数,每个为1的位都是较小的一部分。这样可以用一个循环来解决。下面是快速幂的非递归代码,暂时忽略max
int cal(int x, int n, int max){
int sum = 1; //最后输出的结果
while (n > 0){ //当幂降为0是结束
if (n & 1) //位运算,&是按位与,当两边都为1,表达式为1,这个是用来判断二进制数最后一位是否为1,这里n是以二进制的形式比较的
sum = sum*x%max;//如果为1,sum就要乘x^i,i为该位在二进制数中的位置
n >>= 1; //>>为位运算符,右移一位,即去掉已经计算过的部分
x = x*x%max; //用来标记记录x^2^i,循环i次即去掉了i位,当第i+1位为1时,sum就要乘x^2^i;
}
return sum;//循环结束返回结果。
}
现在来讲max的作用,用来把数变小的,我们可以想象如果是很大的数的很高次方,乘几次后数据非常大无法用任何一个基本数据类型表示,而且这也是不必要的,通常我们只需要知道最后若干位的值,这就可以用到取余了,余数的幂和原数的幂在余数的位数上是相同的,所以每次进行乘法运算后都要取余,当然如果数据很小也可以不用取余。
好了,感觉我已经讲的很详细了!!真的是尽力了。。。
下面贴上上面那题的代码
求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”
Input
输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。
Output
对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行。
简单的说这题就是要求高次幂,有两种方法可以实现。
第一总比较土鳖,每次乘完对1000取余也可以过。
我要讲的是第二种听起来很高大上的方法——快速幂。为什么叫快速幂呢?因为用它求幂非常快,对于x^n,复杂度为O(logn),是不是很吊!快速幂的原理是把幂分解,把一个很大的幂分解成较小的几部分。例如:
11的二进制是1011
11 = 2³×1 + 2²×0 + 2¹×1 + 2º×1
因此,我们将a¹¹转化为
即把n化为2进制数,每个为1的位都是较小的一部分。这样可以用一个循环来解决。下面是快速幂的非递归代码,暂时忽略max
int cal(int x, int n, int max){
int sum = 1; //最后输出的结果
while (n > 0){ //当幂降为0是结束
if (n & 1) //位运算,&是按位与,当两边都为1,表达式为1,这个是用来判断二进制数最后一位是否为1,这里n是以二进制的形式比较的
sum = sum*x%max;//如果为1,sum就要乘x^i,i为该位在二进制数中的位置
n >>= 1; //>>为位运算符,右移一位,即去掉已经计算过的部分
x = x*x%max; //用来标记记录x^2^i,循环i次即去掉了i位,当第i+1位为1时,sum就要乘x^2^i;
}
return sum;//循环结束返回结果。
}
现在来讲max的作用,用来把数变小的,我们可以想象如果是很大的数的很高次方,乘几次后数据非常大无法用任何一个基本数据类型表示,而且这也是不必要的,通常我们只需要知道最后若干位的值,这就可以用到取余了,余数的幂和原数的幂在余数的位数上是相同的,所以每次进行乘法运算后都要取余,当然如果数据很小也可以不用取余。
好了,感觉我已经讲的很详细了!!真的是尽力了。。。
下面贴上上面那题的代码
#include<iostream> using namespace std; int cal(int x, int n, int max){ int sum = 1; while (n > 0){ if (n & 1) sum = sum*x%max; n >>= 1; x = x*x%max; } return sum; } int main(){ int x, n; while ((cin >> x >> n) && (x || n)){ cout << cal(x, n, 1000) << endl; } return 0; }
相关文章推荐
- 找重复数
- powerdesign使用心得
- powerdesign使用心得
- 冒泡排序
- CSS3阴影 box-shadow的使用和技巧总结
- 第3章 语法、关键保留字及变量
- 学神-RHEL7】 1-7-文件权限管理
- 南大软院二十一天成神计划
- RxJava使用场景小结
- 【Android导航 小细节 大成功】项目感悟
- Android FancyCoverFlow的使用实现图片画廊形式的呈现
- visio调整画布大小和旋转画布
- java设计模式之单例模式
- spring 依赖注入
- POJ 2202 哈希
- shell 执行ftp的动作和日志合并
- java设计模式之观察者模式
- java5线程并发库学习之Semaphore
- mahout bayes源码分析总结
- ConcurrentHashMap原理