UVA 11029 Leading and Trailing

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Qin7_Victory/article/details/77265969
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
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


   这是一道有关于幂取模的算法。可能题意大家很容易就能够给读懂,就是求一个数a的n次方,然后输出所求的这个数的前三位和后三位数。可能会有人会有点小疑惑,

会想问,如果这个数没有六位数的话,该怎么办的呢?那小编想提醒你一下,再看一下题,在题的最后一句话已经说明了,这个数的n次方至少有六位数,所以不用担心。

在这里,我也不啰嗦了,我们来进一步的了解一下题。

  求这个数的后三位相信大家掌握的了如指掌了吧。我们可以用二分的方法来进行查找,其简略代码如下:


        

int M(int a , int n)              //二分取模
{
    if(n==1)   return a%1000;
    int x=M(a,n/2);
    long long ans=(long long)x*x%1000;
    if(n&1)   ans=ans*a%M;              //  (n&1) 表示 n%2 == 1
    return (int)ans;
}

   当然也可以运用快速幂的方法查找后三位,其代码如下:

int M(int a,int n)              //快速幂
{
    int m = 1;
    a = a%1000;
    while(n)
    {
        if(n%2)
            m = m*a%1000;
        n = n/2;
        a = (a*a)%1000;
    }
    return m;
}
        以上两种方法都可以实现找后三位数,个人比较赞同用第二种方法,在实践中,就要看个人了,毕竟咋方便咋来了。

       谈完了后三个数,就要我们来看看怎样查找前三个数了。在这里,可能有的人将会了解到一个新的知识  ,那就是关于(double ) fmod (double x,double y),这一个

函数,它是一个关于x对y取余,库函数为<math.h>。说到这,可能会有人会说,我们以前学的那个 % 不是也是取余么,为啥不用它呢,在这里,我就长话短说吧。% 是对整数取余,余数是整数,但是 这个函数就显得格外的特殊,它的余数可以是小数。如果想深入了解,也可以单独查找一些资料。

     

      

       left=(int)pow( 10.0 , 2 + fmod(n*log10(a) , 1) );           //fmod表示的是求余,本题中是求小数部分,可能是负数
    
          

上面这一部分是求前三位数的核心部分。可能会有人对第一句话会有些不理解。我们可以推一下。

文章求得是 a^n , 我们可以把它转换成 10^x 这种情况,  这样 x = n*log10(a),  在这里,那个10 千万千万不要给忘记。有可能会有人问,为什么

要这样转换呢,其实这样转换,我们就可以很轻松的得到这个数了,X可能是一个小数,小数部分的取值范围为 10^0 < y < 10^1 ; 由于求的是三位数

为保证输出有三位数,我们需要 + 2 也就是乘以 10^2。 说到这里,想必大家对于这道题有了更深的理解了吧,还等什么,趁热打铁试一试吧。

下面是整体代码,哦,忘了说了,再输出的时候,可能后面的三位数全部为0,所以不能以%d 的形式输出,我们应该用 %3d。

#include<stdio.h>
#include<math.h>

int M(int a,int n)              //快速幂
{
    int m = 1;
    a = a%1000;
    while(n)
    {
        if(n%2)
            m = m*a%1000;
        n = n/2;
        a = (a*a)%1000;
    }
    return m;
}

int main()
{
    int T,a,n,s=1;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&a,&n);
        int left,right;
        left=(int)pow( 10.0 , 2 + fmod(n*log10(a) , 1) );           //fmod表示的是求余,本题中是求小数部分,可能是负数
        right=M(a,n);
        printf("Case %d: %d %03d\n",s++,left,right);                //03 不能去
    }
    return 0;
}

 


猜你喜欢

转载自blog.csdn.net/Qin7_Victory/article/details/77265969