链接:LightOJ - 1282 Leading and Trailin
题意:
给出
n
  
(
2
≤
n
<
2
31
)
n\;(2\le n\lt 2^{31})
n(2≤n<231) 和
k
  
(
1
≤
k
≤
1
0
7
)
k\;(1\le k\le10^7)
k(1≤k≤107),问
n
k
n^k
nk的前三位和后三位分别为多少?
(题目保证
n
k
n^k
nk最少有6位)
分析:
n k n^k nk的后三位直接快速幂对1000求模即可,比较难处理的是前三位。
设 前三位为
x
x
x,
n
k
n^k
nk共有
m
m
m位,则有:( [x]代表对x向下取整 )
x
=
[
n
k
1
0
m
−
3
]
x=\left [ \frac{n^k}{10^{m-3}} \right ]
x=[10m−3nk]
将其化为:
x
=
[
1
0
lg
n
k
1
0
m
−
3
]
x=\left [ 10^{\lg\frac{n^k}{10^{m-3}}} \right ]
x=[10lg10m−3nk]
lg
n
k
1
0
m
−
3
=
lg
n
k
−
lg
1
0
m
−
3
=
k
lg
n
−
m
+
3
\lg\frac{n^k}{10^{m-3}}=\lg n^k-\lg 10^{m-3}=k\lg n-m+3
lg10m−3nk=lgnk−lg10m−3=klgn−m+3
  
⟹
  
x
=
[
1
0
k
lg
n
−
m
+
3
]
\implies x=\left [ 10^{k\lg n-m+3 } \right ]
⟹x=[10klgn−m+3]
其中
m
=
[
lg
n
k
]
+
1
=
[
k
lg
n
]
+
1
m=[\lg n^k]+1=[k\lg n]+1
m=[lgnk]+1=[klgn]+1
以下代码:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL qpow(LL a,LL b,LL c)
{
LL res=1;
while(b)
{
if(b&1)
res=(res*a)%c;
a=(a*a)%c;
b>>=1;
}
return res;
}
int main()
{
int T,kase=1;
scanf("%d",&T);
while(T--)
{
LL n,k;
scanf("%lld %lld",&n,&k);
double m=floor(k*log10(n))+1; //floor()即向下取整(也可使用强制类型转化)
printf("Case %d: %.f %03lld\n",kase++,floor(pow(10,k*log10(n)-m+3)),qpow(n,k,1000));
//后三位要注意输出前导零
}
return 0;
}