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;
}