题目:求N^N的最右面的那位一位,比如3*3*3=27--- 》7就是所求的
http://acm.hdu.edu.cn/showproblem.php?pid=1061
一般的,我们会写出下面的代码:
#include <iostream>
using namespace std;
int rightD(int n)
{
int s=1;
for (int i=0;i<n;++i)
{
s=(s*n)%10;
}
return s;
}
int main()
{
int numcount=0;//数字的个数
int n=0;
cin>>numcount;
while (numcount-- > 0)
{
cin>>n;
cout<<rightD(n)<<endl;
}
return 0;
}
考虑到,如果出示的n比较大,每次乘的数,可以变成n%10于是,我们得到下面的代码:(注意变量t)
int rightD(int n)
{
int s=1;
int t=n%10;
for (int i=0;i<n;++i)
{
s=(s*t)%10;
}
return s;
}
可是我们拿到评测系统中,还是
Time Limit Exceeded
我们看for循环,每次都执行n次乘法。我们可以一次依次获得n^1 ,n^2, n^4, n^8,所以我们可以很快得到n^n,时间复杂度o(log2 N)所以就有:
#include <iostream>
using namespace std;
int rightD(int n)
{
int ans=1;
int tmp=n%10;
while (n!=0)
{
if(n&1==1)//判断最后一位
{
ans=(ans*tmp)%10;
}
tmp = (tmp*tmp)%10;
n = n>>1;
}
return ans;
}
int main()
{
int numcount=0;//数字的个数
int n=0;
cin>>numcount;
while (numcount-- > 0)
{
cin>>n;
cout<<rightD(n)<<endl;
}
return 0;
}
见下图,第一行,表示1的位置
当然你也可以不使用函数,上图2的位置,就是下面的代码:
#include<iostream>
using namespace std;
int main()
{
int a,ans,n=0;
double dval = 0;
int count=0;
cin>>n;
while(n--)
{
cin>>a;
ans=1;
count=a;
a = a%10;
while (count)
{
if (count&1==1)
ans=(ans*a)%10;
a=(a*a)%10;
count>>=1;
}
cout<<ans<<endl;
}
return 0;
}
到此可以说,该题目已经完结了,但是本题可以使用静态表的方法,时间复杂度o(1)。
我们看一下n= (0 - 99),的结果:
0 1 4 7 6 5 6 3 6 9
0 1 6 3 6 5 6 7 4 9
0 1 4 7 6 5 6 3 6 9
0 1 6 3 6 5 6 7 4 9
0 1 4 7 6 5 6 3 6 9
0 1 6 3 6 5 6 7 4 9
0 1 4 7 6 5 6 3 6 9
0 1 6 3 6 5 6 7 4 9
0 1 4 7 6 5 6 3 6 9
0 1 6 3 6 5 6 7 4 9
所以有下面代码:
#include <iostream>
using namespace std;
unsigned int buf[20]={0,1,4,7,6,5,6,3,6,9,
0,1,6,3,6,5,6,7,4,9,
};
int main()
{
int numcount=0;
int n=0;
cin>>numcount;
while (numcount-- > 0)
{
cin>>n;
cout<<buf[n%20]<<endl;
}
return 0;
}
也是可以的,呵呵