数论(浮点数的幂) - Leading and Trailing - LightOJ 1282
题意:
给定两个数n,k,求nk的前三位和最后三位。
输入:
T组测试数据,
每组包括两个正整数n和k。
输出:
nk的前三位和最后三位。
Sample Input
5
123456 1
123456 2
2 31
2 32
29 8751919
Sample Output
Case 1: 123 456
Case 2: 152 936
Case 3: 214 648
Case 4: 429 296
Case 5: 665 669
数据范围:
T≤1000,2≤n<231,1≤k≤107
分析:
首先,求后三位是非常方便的,快速幂对1000取模即可,注意输出时要考虑前导0。
问题在于求前三位。
对于任意正整数x,n=10lg(n)=10x+y,x是lg(n)的整数部分,y是lg(n)的小数部分,
10x是将10y的小数点向右移动x位,10y即n×10x1,因此,我们要求n的前三位,就将10y×100,取整数部分即可。
求lg(n)的小数部分,可用函数:
fmod(log10(n),1);
计算log10(n)对1取模的值。
本题要计算nk,即计算10klg(n)
我们先计算klg(n)的小数部分y,再计算n的前三位为10y×100.
疑问:为何采取这样的方法来求前三位?
k个n相乘会爆精度,但是k×lg(n)不会。快速幂取模也不会。
由此能够感受到这种技巧的好处。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
using namespace std;
int T,k;
ll n;
ll quick_pow(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1) res=res*a%1000;
a=a*a%1000;
b>>=1;
}
return res;
}
int main()
{
cin>>T;
for(int t=1;t<=T;t++)
{
cin>>n>>k;
double y=fmod((double)k*log10(1.0*n),1);
int head=pow(10,y)*100;
int tail=quick_pow(n,k);
printf("Case %d: %03d %03d\n",t,head,tail);
}
return 0;
}