计算N的M次方的最后3位数

题目:计算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";

}
 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值