数论(浮点数的幂) - Leading and Trailing - LightOJ 1282

数论(浮点数的幂) - Leading and Trailing - LightOJ 1282

题意:

n , k n k 给定两个数n,k,求n^k的前三位和最后三位。

输入:

T T组测试数据,

n k 每组包括两个正整数n和k。

输出:

n k n^k的前三位和最后三位。

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 < 2 31 1 k 1 0 7 T≤1000,2 ≤ n < 2^{31},1 ≤ k ≤ 10^7


分析:

便 1000 0 首先,求后三位是非常方便的,快速幂对1000取模即可,注意输出时要考虑前导0。

问题在于求前三位。

x n = 1 0 l g ( n ) = 1 0 x + y x l g ( n ) y l g ( n ) 对于任意正整数x,n=10^{lg(n)}=10^{x+y},x是lg(n)的整数部分,y是lg(n)的小数部分,

1 0 x 1 0 y x 1 0 y n × 1 1 0 x n 1 0 y × 100 10^x是将10^y的小数点向右移动x位,10^y即n×\frac{1}{10^x},因此,我们要求n的前三位,就将10^y×100,取整数部分即可。

l g ( n ) 求lg(n)的小数部分,可用函数:

fmod(log10(n),1);

l o g 10 ( n ) 1 计算log_{10}(n)对1取模的值。

n k 1 0 k l g ( n ) 本题要计算n^k,即计算10^{klg(n)}

k l g ( n ) y n 1 0 y × 100. 我们先计算klg(n)的小数部分y,再计算n的前三位为10^y×100.

疑问:为何采取这样的方法来求前三位?

k n k × l g ( n ) 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;
}

猜你喜欢

转载自blog.csdn.net/njuptACMcxk/article/details/107735604