题意:给出n和k(int范围内)。求 n 的 k 次方这个数的前三位和后三位数字。
思路:对于后三位只需要快速幂取模,log 2 n 的复杂度对于 100W 的数据来说不算什么。不过这里需要注意处理乘法溢出。
而要得到前三位,需要用一个高中学过的“对数函数“。
对于 X 令a= log10X。i 是 a 的整数部分。d 是 a 的小数部分。
a的整数部分 i 只反映 X 小数点的位置。小数部分d反应x的数码(重点)
如果把 a 的整数部分去掉。剩下的 d取次幂。结果就会反映X的数码了。
公式说明如下:
由上可得: a=i+d;(i,d还是上面的含义)
令 k = 10d 。由于 0<d<1 所以="" 1<k="" <="" 10,<="" p="">
d = a – i ; k = 10a/ 10i .这里i是整数
所以 k 可以看做是X 除以10直到范围落在1到10之间。
k的形式是a.bcdef 那么abc就是我们想要的了。
回归到本题的解决办法。对于n的k次方 可以用公式 log10nk= k * log10n 求得对数指,然后处理整数部分到2(想想为什么?提示:和答案要求的前3位有关)。得到 a,再算出b = 10a.答案就是b的整数部分了。
#include<iostream>
#include<cstdio>
#include<limits.h>
#include<cmath>
#include<cstdlib>
#include<cstring>
using namespace std;
int f1(int n,int k){ //求n的k次方前三位。
double a = (log (n)/log(10.0) )* k;
int b = a ;
a=a-b + 2; //整数部分的处理
a= pow ( 10.0 , a ) ;
return b=(a+0.000000001); //浮点数误差控制
}
int f2(int n,int k){ //求n的k次方后三位,快速幂取模
if(k==0)
return 1;
int ans=f2( n , k/2 );
ans=(ans*ans)%1000;
if(k%2==1)
ans=(ans*n)%1000;
return ans;
}
int main(){
int t ,n ,k ;
scanf( "%d" ,&t );
while(t--) {
scanf("%d%d",&n,&k);
int a1 = f1(n,k);
int a2 = f2(n%1000,k);
if(a2==0){ //题目的格式要求。这里容易贡献一个Wa
printf("%d...000\n",a1);
continue;
}
if(a2<10){
printf("%d...00%d\n",a1,a2);
continue;
}
if(a2<100){
printf("%d...0%d\n",a1,a2);
continue;
}
printf("%d...%d\n",a1,a2);
}
return 0;
}