hdu1061 快速幂取余

http://acm.hdu.edu.cn/showproblem.php?pid=1061

题意是给定一个整数N,求出N^N的个位数,那么这个题目其实也就是我们所说的 (a^b) %c,快速幂取余了。

先来看看传统的算法

int ans = 1;
for (int i = 1; i <= N; i++)
    ans *= N;

毫无疑问,这种代码在N大到一定范围之后,所用的时间复杂度是非常高的,用在本题上也一定会超时。

那么我们就需要用到快速幂取余这个算法了。先给出一个公式:

(a * b) % c = (a % c) * (b % c) % c

那么我们可以把 b 看成是它的每一个二进制位进行运算,二进制位为0的不必进行运算,我们只需要计算二进制位为1的就可以了。

贴出代码:

#include <iostream>
using namespace std;

int main()
{
    int T, n;
    cin >> T;
    while (T--)
    {
        cin >> n;
        int ans = 1;
        int b = n;
        int a = n % 10; //预处理,确保 a 在10的范围之下
        while (b)
        {
            if (b&1)
                ans = (ans * a) % 10;     //如果n的二进制位不是0,那么我们的结果是要参与运算的
            b >>= 1;                  //二进制的移位操作,相当于每次除以2,用二进制看,就是我们不断的遍历b的二进制位
            a = (a*a) % 10;         //不断地加倍
        }
        cout << ans << endl;
    }
    return 0;
}

还有另外一种算法,是通过找规律。

我们发现:如果N的尾数是1、5、6那么最后的尾数也一定是1、5、6

如果是4、9,那么就是每运算两次就会重复;剩余的每运算四次就会重复。因此规律就找出来了。

代码如下:

#include <iostream>
#include <string>
using namespace std;

int main()
{
    int a[10][4]={{0},{1},{6,2,4,8},{1,3,9,7},{6,4},{5},{6},{1,7,9,3},{6,8,4,2},{1,9}};
    int n;
    cin >> n;
    while(n--)
    {
        int num;
        cin >> num;
        int h = num % 10;
        if(h == 0 || h == 1 || h == 5 || h == 6)
            cout << h << endl;
        else if(h == 4 || h == 9)
            cout << a[h][h%2] << endl;
        else cout << a[h][h%4] << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_39548163/article/details/81192623
今日推荐