小白详细讲解快速幂--杭电oj2035-A^B

Problem Description

求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的作用,用来把数变小的,我们可以想象如果是很大的数的很高次方,乘几次后数据非常大无法用任何一个基本数据类型表示,而且这也是不必要的,通常我们只需要知道最后若干位的值,这就可以用到取余了,余数的幂和原数的幂在余数的位数上是相同的,所以每次进行乘法运算后都要取余,当然如果数据很小也可以不用取余。

  好了,感觉我已经讲的很详细了!!真的是尽力了。。。

下面贴上上面那题的代码

 1 #include<iostream>
 2 using namespace std;
 3
 4 int cal(int x, int n, int max){
 5     int sum = 1;
 6     while (n > 0){
 7         if (n & 1)
 8             sum = sum*x%max;
 9         n >>= 1;
10         x = x*x%max;
11     }
12     return sum;
13 }
14 int main(){
15     int x, n;
16     while ((cin >> x >> n) && (x || n)){
17         cout << cal(x, n, 1000) << endl;
18     }
19     return 0;
20 }
时间: 2024-10-13 12:05:17

小白详细讲解快速幂--杭电oj2035-A^B的相关文章

快速幂取余算法

下面是一个快速幂的介绍: 先贴一个秦九韶算法(Horner算法)的原理: 设有项的次函数 将前项提取公因子,得 再将括号内的前项提取公因子,得 如此反复提取公因子,最后将函数化为 令 ...... 则即为所求 下面是讲解快速幂的:(By  夜せ︱深   感谢作者) 快速幂取模算法 在网站上一直没有找到有关于快速幂算法的一个详细的描述和解释,这里,我给出快速幂算法的完整解释,用的是C语言,不同语言的读者只好换个位啦,毕竟读C的人较多~ 所谓的快速幂,实际上是快速幂取模的缩写,简单的说,就是快速的求

数据结构15——快速幂

一.相关介绍 快速幂 做到快速求幂 时间复杂度:O(logn) 问题引入 题目:求ab 朴素解法:将a连乘b次,那么对应的时间复杂度就是O(b),即O(n). 快速幂法:关于此题的快速幂法会在下面的算法实现提及. 二.算法实现 下面以求ab的过程为例讲解快速幂的实现: b可以转换为二进制数,该二进制数第i位的位权为2i-1 例如,当b==11时,a11=a2^0+2^1+2^3,11的二进制是1011,11 = 23×1 + 22×0 + 21×1 + 20×1,因此,我们将a11转化为算 a(

杭电 HDU ACM 1061 Rightmost Digit

Rightmost Digit Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 37888    Accepted Submission(s): 14268 Problem Description Given a positive integer N, you should output the most right digit of

快速幂算法的理解

首先给出代码: #include <iostream> using namespace std; //计算a^bmodn int modexp(int a,int b,int n) { int ret=1; int tmp=a; while(b) { if(b&1) ret=ret*tmp%n; tmp=tmp*tmp%n; b>>=1; } return ret; } int main() { cout<<modexp(2,10,3)<<endl;

蟠桃记《快速幂》(两种解法)

这道题比较容易所以解法也并不唯一.但是我们主要通过这道题讲解快速幂的算法. 题目如下: 喜欢西游记的同学肯定都知道悟空偷吃蟠桃的故事,你们一定都觉得这猴子太闹腾了,其实你们是有所不知:悟空是在研究一个数学问题! 什么问题?他研究的问题是蟠桃一共有多少个! 不过,到最后,他还是没能解决这个难题,呵呵^-^ 当时的情况是这样的: 第一天悟空吃掉桃子总数一半多一个,第二天又将剩下的桃子吃掉一半多一个,以后每天吃掉前一天剩下的一半多一个,到第n天准备吃的时候只剩下一个桃子.聪明的你,请帮悟空算一下,他第

杭电 2035 人见人爱A^B【快速幂取模】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2035 解题思路:这一题数据不大,可以用同余来做,也可以用快速幂来做 反思:定义成 #include<stdio.h> int quick_mod(int a,int b,int m) { int ans=1; while(b) { if(b&1) { ans=(ans*a)%m; b--; } b=b>>1; a=a*a%m; } return ans; } int main(

葫芦娃关于快速幂流程的详细讲解

快速幂的流程大概是这样的,维护一个等式a^b=x^y*z. 比如说现在求3的10次方 第一步:3^10=3^10*1 第二步:3^10*1=9^5*1 第三步:9^5*1=9^4*9 第四步:9^4*9=81^2*9 第五步:81^2*9=6561^1*9 第六步:6561^1*9=1^1*59049 所以3^10=59049 上面总共进行了五次乘法运算,相比较朴素的十次来说,要好一些 经过上面的演算,抽象成自然语言大概是这样: 初始化,x=a,y=b,z=1, 每一次,首先如果y不大于0则退出

杭电 4506 小明系列故事——师兄帮帮忙【快速幂取模】

题目:小明自从告别了ACM/ICPC之后,就开始潜心研究数学问题了,一则可以为接下来的考研做准备,再者可以借此机会帮助一些同学,尤其是漂亮的师妹.这不,班里唯一的女生又拿一道数学题来请教小明,小明当然很高兴的就接受了.不过等他仔细读题以后,发现自己也不会做,这下小明囧了:如果回复说自己不懂,岂不是很没面子? 所以,他现在私下求你帮忙解决这道题目,题目是这样的: 给你n个数字,分别是a1,a2,a3,a4,a5……an,这些数字每过一个单位时间就会改变,假设上一个单位时间的数字为a1’,a2’,a

杭电 2817 A sequence of numbers【快速幂取模】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2817 解题思路:arithmetic or geometric sequences 是等差数列和等比数列的意思, 即令输入的第一个数为a(1),那么对于等差数列 a(k)=a(1)+(k-1)*d,即只需要求出 a(k)%mod   又因为考虑到k和a的范围, 所以对上式通过同余作一个变形:即求出 (a(1)%mod+(k-1)%mod*(d%mod))%mod 对于等比数列 a(k)=a(1)*q