http://acm.hdu.edu.cn/showproblem.php?pid=2035
人见人爱A^B
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 21773 Accepted Submission(s): 15165
Problem Description
求A^B的最后三位数表示的整数。
说明:A^B的含义是“A的B次方”
说明:A^B的含义是“A的B次方”
Input
输入数据包含多个测试实例,每个实例占一行,由两个正整数A和B组成(1<=A,B<=10000),如果A=0, B=0,则表示输入数据的结束,不做处理。
Output
对于每个测试实例,请输出A^B的最后三位表示的整数,每个输出占一行
Sample Input
2 3 12 6 6789 10000 0 0
Sample Output
8 984 1
Author
lcy
Source
10000^10000次怎么想也是超过了long的存储范围,所以暴力运算pow(10000,10000)求解是根本不行的!而且这道题目的时间限制也是在1S秒,如果你暴力求解时间复杂度O(n*n),n=10000的时候也肯定是超时的!
为了解决溢出问题,我们不能再完全计算后取摸,我们可以在a^b可以看成a*a*a.......(b个a相乘),我们可以在每两个a相成之后取模,那么第一次我们就可以分成(如果b一直都是偶数)b/2组a*a%1000,然后把每组a*a%1000的值赋值给a,b= b/2;这样在我们有面对的就是a^b模型了。一直迭代下去一直到b==1为止!输出b==1的时候a的值就是所要的结果!这样又解决了时间超时的问题,这种算法的时间复杂度为O(log2(n));
刚才我们假设的是b一直是偶数的情况,当时这种情况是极少发生的(当且仅当a = 2^n的时候成立)这个时候我们需要考虑如果b%2 != 0的情况也就是说b是奇数,这说明了在某次运算时候这些a*a*a...必定存在一个落单的a。尽管它是落单的,但是它也在影响着最后的结果。为了解决这个问题,我们可以定义一个变量用来收集所有在计算过程中落单的a;这里我初始化int left = 1;每次有落单的a,left = left *a%1000;这样我们就收集了所有落单的a;
好了分析到这里我们用代码说话吧!
#include<iostream>
using namespace std;
int main(){
int A,B;
while(cin>>A>>B){
int left=1;
int result;
if(A == 0)break;
while(B!=2&&B!=1){
if(B%2==1){
B--;
left = left*A%1000;
A = A*A%1000;
B = B/2;
}else{
A = A*A%1000;
B = B/2;
}
}
if(B==2){
result = A*A%1000;
result = result*left%1000;
}else{
result = A*left%1000;
}
cout<<result<<endl;
}
return 0;
}