杭电 1061 Rightmost Digit计算N^N次方的最后一位

来源:互联网 发布:淘宝能处理服装库存么? 编辑:程序博客网 时间:2024/05/17 01:26

题目:求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;  }


也是可以的,呵呵