美文网首页考研计算机机试刷题修炼
记清华2010计算机机试题目

记清华2010计算机机试题目

作者: 故梦_三笙 | 来源:发表于2019-04-14 10:49 被阅读6次

    题目如图所示。这道题的难点在于x,y会溢出int的范围,所以我一开始想的是用大精度整数做,但是又要幂和模运算,那样就更麻烦了。所以我看了一下大佬的做法,发现了两种做法:二分求幂和快速模幂运算。



    二分求幂:

    首先介绍一下什么是二分求幂。如下图所示:

    来看代码:

    这是剑指offer的递归代码,名字起的怪怪的,不太想看哈哈

    下面是王道机试指南的非递归

    简单的举个例子就好懂了。

    假设我要求2^10.那么就可以转化为2^5 * 2^5,然后2^5转化为2^2*2^2*2^1,继续下去就是2^1*2^1*2^1*2^1*2^1,这样就把一个大的数转化成口算出来的小数了,当然这个例子不是太好,如果举个大一点的数,就更好理解为什么要用二分求幂了。

    了解了二分求幂后,来看这道题,首先这道题的精髓就在于接下来的分析,请仔细阅读:

    对于root(N, k)中的N,我们可以把N看作关于k的多项式,也就是N = a0 + a1*k + a2*k^2  + … +  an* k^n,而我们要求的root函数就是这个多项式的系数和,也就是a0 + a1 + a2 + ... +  an。下面我们考虑root(N^2, k)。此时N^2 = (a0 + a1*k + a2*k^2 + … + an*  k^n)^2,而这个多项式展开后的系数和是(a0 + a1 + a2 + … +  an)^2,这个结果刚好就是先对N取root函数再平方的结果。实际上,我们很容易就能看出,多项式先乘方再取系数和(先乘再去掉k)与先取系数和再乘方(先去掉k再乘),结果是一样的(因为有没有k并不影响系数间的相乘,也不影响相乘之后的求和),于是乎,我们可以得到以下的递推公式:

    root(x, y, k) = root((root(x, y / 2, k))^2, 1, k), y为偶数  

    root(x, y, k) = root((root(x, y / 2, k))^2 * root(x, 1, k), 1,k),y为非1的奇数

    root(x, 1, k) = x % k + x / k % k + ...(大于k的话再重复求root) 

    这和二分求幂的思想类似。来看代码

    #include <stdio.h>

    int root(int N,int k)

    {

        int sum;

        while(N>=k)

        {

            sum=0;

            while(N)

            {

                sum=sum+N%k;

                N/=k;

            }

            N=sum;

        }

        return N;

    }

    int main()

    {

      int x,y,k;

        while(scanf("%d%d%d",&x,&y,&k)!=EOF)

        {

            int sum=1;

            int temp=root(x,k);

            while(y)

            {

                if(y%2!=0)

                    sum=root(sum*temp,k);

                temp=root(temp*temp,k);

                y/=2;

            }

            printf("%d",sum);

        }

    }


    快速模幂运算

    对于快速模幂运算的介绍,我也是从一个博主哪里看到的。快速幂、快速幂取模的分析与代码实现 - iwts - CSDN博客

    再看这道题的运用

    由上述推导得出,问题就转化为求N%(k-1);这样就可以轻松的应用快速模幂运算了。代码我就不写了,主要是思想。

    相关文章

      网友评论

        本文标题:记清华2010计算机机试题目

        本文链接:https://www.haomeiwen.com/subject/zgdjwqtx.html