题目链接:https://vjudge.net/problem/LightOJ-1282
Time Limit: 2 second(s) | Memory Limit: 32 MB |
You are given two integers: n and k, your task is to find the most significant three digits, and least significant three digits of nk.
Input
Input starts with an integer T (≤ 1000), denoting the number of test cases.
Each case starts with a line containing two integers: n (2 ≤ n < 231) and k (1 ≤ k ≤ 107).
Output
For each case, print the case number and the three leading digits (most significant) and three trailing digits (least significant). You can assume that the input is given such that nk contains at least six digits.
Sample Input |
Output for Sample Input |
5 123456 1 123456 2 2 31 2 32 29 8751919 |
Case 1: 123 456 Case 2: 152 936 Case 3: 214 648 Case 4: 429 296 Case 5: 665 669 |
题意:
求 n^k 的前三位和后三位。2 ≤ n < 231,1≤ k ≤ 107
题解:
1.后三位快速幂求模即可。
2.对于前三位,可知任何一个正整数可以表示为 10^(x+y),为何能表示正整数?联想一下指数函数的曲线。规定x是整数,y是小于1的浮点数。因为 10^(x+y) = 10^x*10^y,所以,10^x决定了这个数的最高位为第x位,10^y决定了这个数的数值。类似于科学计数法 a*10^b,其中 10^y对应a, 10^y对应10^b。
3.有了上述结论,那么就可以: n^k = 10^(x+y)。两边取对数,得k*log10(n) = x+y。由于我们需要的是数值,而不是位数,所以只取对数值有用的信息,即y,自带函数fmod()能实现这个功能。得到y之后,10^y就是数值了,由于要前三位,所以直接乘以100即可。
4.很多时候,指数都不太好计算,一般都转化为对数进行操作(高数经常有这样的转化)。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int mod = 1e9+7; 17 const int MAXM = 1e5+10; 18 const int MAXN = 5e5+10; 19 20 LL qpow(LL x, int y) 21 { 22 LL s = 1; 23 while(y) 24 { 25 if(y&1) s = (1LL*s*x)%1000; 26 x = (1LL*x*x)%1000; 27 y >>= 1; 28 } 29 return s; 30 } 31 32 int main() 33 { 34 int T, kase = 0; 35 scanf("%d", &T); 36 while(T--) 37 { 38 LL n, k; 39 scanf("%lld%lld", &n,&k); 40 int most = 100*pow(10, fmod(k*log10(n),1)); 41 int least = qpow(n, k); 42 printf("Case %d: %03d %03d ", ++kase, most, least); 43 } 44 }