今天,就来说说杭电n^m!

杭电1061

先上题目:

Rightmost Digit

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 31556    Accepted Submission(s): 12068


Problem Description
Given a positive integer N, you should output the most right digit of N^N.
 


 

Input
The input contains several test cases. The first line of the input is a single integer T which is the number of test cases. T test cases follow.
Each test case contains a single positive integer N(1<=N<=1,000,000,000).
 


 

Output
For each test case, you should output the rightmost digit of N^N.
 


 

Sample Input
  
  
2 3 4
 


 

Sample Output
  
  
7 6
Hint
In the first case, 3 * 3 * 3 = 27, so the rightmost digit is 7. In the second case, 4 * 4 * 4 * 4 = 256, so the rightmost digit is 6.
 


 

Author
Ignatius.L
 


 

Recommend
 


 

Statistic  |  Submit  |  Discuss | Note
 
 
解题思路:
三种方法
 
1.直接计算(如果你有足够的时间的话!)
代码如下:
scanf("%d",&n);
  pr=1;
          for(i=1;i<=n;i++){
   pr=(pr*(n%10))%10;
  }
  
   printf("%d\n",pr);
 
 
当然,这在杭电上会超时!因为n足够大的时候,循环次数会较多!不妨可以试试哦!
 
2.就像求素数那样,事先打一个余数表,a[ i ] 存的都是 i^i 的余数,
代码如下:
int a[100000010];
void solve(){
 int i,j;
 memset(a,0,sizeof(a));
 a[1]=1;
 for(i=2;i<1000000010;i++){
  a[i]=(a[i-1]*(i%10))%10;
 }
}
 
这样的确可以,(对于测试数据较小的时候),此时定义的a[100000010]  的程序能够运行,但杭电上的数据正好,又多了一个0;
那好,我们就加上一个0;   运行时,出现了问题,说定义的数组太大,,,,怎么办呢,,,,回忆一下,我们定义的是整型的数组a[1000000010],,,整形四个字节,,并且,根据需要,我们在a数组中只是存放0~10之间的数,那么我们就没有必要用整形,我们完全可以用字符型数组代替,那好,我们就改一下,,,,,,
如下:
char a[1000000010];
void solve(){
 int i,j;
 memset(a,0,sizeof(a));
 a[1]=1;
 for(i=2;i<1000000010;i++){
  a[i]=(a[i-1]*(i%10))%10;
 }
}
 
运行,,!哎呀,这次果然没报错,,那好,我们就提交一下,,,提交得到的是Memory Limit Exceeded,超内存了,,看一下程序内存,70多兆,那必须超啊!所以本题用打余数表的方法不是超时,就是超内存,所以这种打表方法在本题是行不通的,我们还要另寻他法,,接下来,就有了3
 
3.简化运算步骤
 
由上两种方法可知,打余数表,内存太大,,直接运算呢,超时,,,等等,既然运算超时,那一定是运算的时候,运算次数太多了,那么我们是否可以简化一下运算步骤呢,,当然可以,
 
根据 剩余定理可知:
 
                                  (n^m)%10=((n%10)^m)%10
 
然而,先进行求余,是减小了n,,在一定成度上减少了运算次数,关键是把m也减小,这样才能最大程度的较少运算次数,为此,我们可以进行降幂处理
如下:
               m为偶数:  n^m=(n*n)^(m/2)
              
               m为奇数时:n^m=n*(n*n)^(m/2)
 
  根据剩余定理:得  m为偶数:  (n^m)%10=(((n*n)%10)^(m/2))%10
              
                                    m为奇数时:n^m=n*(n*n)^(m/2)  同样是这样
 
由此可得代码如下:
 
 int solve(int n,int m){
 if(m==0) return 1;
 if(m==1) return n;
 if(m%2==0) return solve(n*n%10,m/2);
 if(m%2!=0) return n*solve(n*n%10,(m-1)>>1)%10;
}
 
 
这也是一个较常用的代码片段,完整代码如下:

# include<stdio.h>
int solve(int n,int m){
 if(m==0) return 1;
 if(m==1) return n;
 if(m%2==0) return solve(n*n%10,m/2);
 if(m%2!=0) return n*solve(n*n%10,(m-1)>>1)%10;
}


int main(){
    int n;
    int m,i;
    scanf("%d",&n);
    while(n--){
  scanf("%d",&m);
  printf("%d\n",solve(m%10,m));
 }
 return 0;
}

4,,??这应该也算得上一种方法:

 

将1到40 的n^n运算打印出来,可以惊奇的发现,数是以20为周期,循环的,,那么,我们就又能做点"手脚"了  嘿嘿!!

如下:

#include<iostream>
using namespace std;
int main()
{
    int t,a[21]={0,1,4,7,6,5,6,3,6,9,0,1,6,3,6,5,6,7,4,9,0};
    __int64 n;

    cin>>t;
    while(t--)
    {
        cin>>n;
        cout<<a[n%20]<<endl;
    }
    return 0;
}

 

解题时间:2014~07~28

解题人:李富昌

仅供参考!

weixin151云匹面粉直供微信小程序+springboot后端毕业源码案例设计 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值