Leading and Trailing
题面
题意
输出
n
k
n^{k}
nk的前3位数与后3位数,如果位数不够补0。
分析
n
k
n^{k}
nk的后三位,相对而言,是容易求出的。我们可以直接用快速幂取模的方法,对
n
k
n^{k}
nkmod1000,即可以得到我们所要求的答案。但是这题的难点主要是怎么求前三位,接下来我来重点讲一下怎么推导求前三位的方法。
推导
n
k
n^{k}
nk=
1
0
l
g
n
k
10^{lgn^{k}}
10lgnk=
1
0
k
∗
l
g
n
10^{k*lgn}
10k∗lgn,设
k
∗
l
g
n
=
a
+
b
(
其
中
a
是
整
数
,
b
是
小
数
)
k*lgn=a+b(其中a是整数,b是小数)
k∗lgn=a+b(其中a是整数,b是小数)
那么
n
k
n^{k}
nk=
1
0
l
g
n
k
10^{lgn^{k}}
10lgnk=
1
0
k
∗
l
g
n
=
1
0
a
+
b
=
1
0
a
∗
1
0
b
10^{k*lgn}=10^{a+b}=10^{a}*10^{b}
10k∗lgn=10a+b=10a∗10b
我们可以知道
1
0
a
10^{a}
10a并不会改变前3位数的大小,仅仅改变位置,但是
1
0
b
10^{b}
10b中b是小数,所以会改变前3位数的大小
1
=
1
0
0
<
=
1
0
b
<
1
0
1
=
10
(
0
<
=
b
<
1
)
1=10^{0}<=10^{b}<10^{1}=10 (0<=b<1)
1=100<=10b<101=10(0<=b<1),这下问题就转化为如何求b?
如何求b呢
modf()函数
利用这个函数就可以把
k
∗
l
g
n
k*lgn
k∗lgn的b算出来,那么我们还要分析一下
k
∗
l
g
n
k*lgn
k∗lgn是否会出现数据范围爆出的问题,double可控制的是16位,而
k
∗
l
g
n
<
1
e
9
k*lgn<1e9
k∗lgn<1e9.所以可实现。
AC代码
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
ll n,k,fir,res;
double x,y;
ll quick_mod(ll a,ll b,ll p){
ll num=a,sum=1;
while(b){
if(b&1){
sum=sum*num%p;
}
num=num*num%p;
b>>=1;
}
return sum;
}///a^b mod p*/
int main(){
int t,num=1;
cin>>t;
while(t--){
scanf("%lld%lld",&n,&k);
res=quick_mod(n,k,1000);///res表示后三位
y=modf((double)(k*log10(n)),&x);
fir=pow(10,y)*100;
printf("Case %d: %03lld %03lld\n",num++,fir,res);
}
return 0;
}