题目:计算N的M次方的最后3位数。N,M都是正整数,都大于12.
解题思路是:
归结为求任意两位正整数的乘积的最后3位数,这里主要是要解决阶乘很高的时候的效率问题。
任意两位正整数的乘积的最后3位数,受影响于乘数和被乘数的最后3位数,需要有这样的一个基本过程,暂且叫做calc_two_3吧。
方法一:
简单循环:从1到M,逐个循环相乘,在阶乘很大的时候,这个速度很慢。。。。
方法二:
利用对数的方法:先2个数相乘,然后,平方一下这个结果,再平方一下这个结果,直到算完为止,这样,运算量会小很多。
再把中间的计算结果缓存下来,直接使用,速度更快了。
代码如下:
/**
计算N的M次方的最后3位数
*/
#include <iostream>
#include <math.h>
using namespace std;
int calc_two_3(int a,int b){
if(a>1000){
a=a%1000;
}
if(b>1000){
b=b%1000;
}
return (a*b)%1000;
}
int log2N(int N){
return log10(N)/log10(2);
}
int simple(int base,int index){
int res=base;
int i=0;
for(i=0;i<index-1;i++){
res=calc_two_3(res,base);
}
return res%1000;
}
int entry(int base,int index){
int res=base;
int cal_idx=1;//一次使用的次数,这个是2的指数,如等于1,即为2的1次方为2
int pre_res=1;
int end=index;
int cache[100][1];//保存的计算结果
int i=0;
for(i=0;i<100;i++){
cache[i][0]=-1;
}
while(1){
cout<<"end="<<end<<",cal_idx="<<cal_idx<<",pre_res="<<pre_res<<"\n";
while(pow(2,cal_idx)<=end){
res=calc_two_3(res,res);
cout<<"cal_idx="<<cal_idx<<",pow(2,cal_cum)="<<pow(2,cal_idx)<<",end="<<end<<",res="<<res<<"\n";
cache[cal_idx][0]=res;
cal_idx++;
}
pre_res=calc_two_3(pre_res,res);
end-=pow(2,cal_idx-1);
//判断是否在cache有对应的
do{
if(end==0){
break;
}
int tmp_idx=log2N(end);
if(cache[tmp_idx][0]==-1){
break;
}
if(cache[tmp_idx][0]!=-1){
//直接使用
cout<<"use cache idex="<<tmp_idx<<",cache result is "<<cache[tmp_idx][0]<<"\n";
pre_res=calc_two_3(pre_res,cache[tmp_idx][0]);
end-=pow(2,tmp_idx);
}
}
while(1);
cal_idx=1;
res=base;
if(end==0){
break;
}
}
res=pre_res;
cout<<"index="<<index<<",cal_idx="<<cal_idx<<",pow(2,cal_idx)="<<pow(2,cal_idx)<<",res="<<res<<"\n";
return res%1000;
}
int main(){
cout<<"ok\n";
int base=13;
int index=1553214445;
cout<<"输入base=";
cin>>base;
cout<<"\n输入index=";
cin>>index;
cout<<"\nbase="<<base<<",index="<<index<<"\n";
int res1=entry(base,index);
cout<<"\n---------------\nentry(base,index)="<<res1<<"\n";
//int res2=simple(base,index);
//cout<<"\nsimple(base,index)="<<simple(base,index)<<"\n";
}