Num 16: HDOJ: 题目1061 : Rightmost Digit [ 求个位数 ] [ 快速幂算法 ]
2015-07-27 15:18
531 查看
题目:
Total Submission(s): 39386 Accepted Submission(s): 14861
[align=left]Problem Description[/align]
Given a positive integer N, you should output the most right digit of N^N.
[align=left]Input[/align]
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).
[align=left]Output[/align]
For each test case, you should output the rightmost digit of N^N.
[align=left]Sample Input[/align]
[align=left]Sample Output[/align]
刚看到题的时候就应该意识到,一定不能强行计算 N^N%10 然后输出,计算量大,而且会数据溢出;
大数乘法在这里也不太合适,毕竟要算N次方,就算计算出来,submit 的时候也不能够保证不超时;
所以感觉到应该是有内在规律,仔细研究后发现:
1.
在计算 N^N 的个位数的时候,个位数的数值仅与N的个位数有关;
所以可以利用计算( N%10 )^N 的个位数来代替原题;
2.
进一步的,演算后发现1-9的N( N>0 )次方按4个数一循环;
例:3的1-9次方的个位数依次为 ( 3, 9,7,1,3,9,7,1,3) ;
所以对于次方数也可以做简化,次方为:N%4 ;
这里要注意,当N%4==0的时候N应当取4;( 否则X^0=1,只会输出1 )
通过以上的分析,我们就将问题转化为求 ( N%10 )^( N%4 )的个位数的问题了;
大大简化了计算过程,而且保证了数据一定不会溢出;
AC代码:
注意:pow函数的格式pow( double x, int index ),要学会利用类型的强制转换;
见网上也有许多人在说用快速幂的方法也可以做;
这里仅介绍快速幂算法,不推荐在这道题上使用快速幂的方法;
快速幂:
分为二分法和位运算( 位操作 );
原理:
例如在计算 2^4 的时候,当计算过 2^2后, 可以直接计算 ( 2^2 )^2即可;
1.二分法:
2.位运算:
原理和二分法相似,只不过是通过位运算来对数据做处理的;
我们也可以用计算快速幂的方法来进行余数的计算( 求个位数即对10取余 ):
这里用到的方法为:
快速幂取模算法:
利用离散数学之中所讲的知识,我们有公式:
( a^b ) mod c=( a mod c )^b mod c ;
通过数学知识,我们可化简此等式有( 可循环[ 递归 ]计算 ):
奇数时:(a mod c) * ( a^2 mod c)^( b/2 ) mod c ;
偶数时: a^2 mod c)^( b/2 ) mod c ;
所以在计算 N^N 的个位数的时候,解决了 N^N可能太大存不下的问题,也减少了步数:
函数用于
a^b%c 的快速计算 ;
Rightmost Digit
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 39386 Accepted Submission(s): 14861
[align=left]Problem Description[/align]
Given a positive integer N, you should output the most right digit of N^N.
[align=left]Input[/align]
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).
[align=left]Output[/align]
For each test case, you should output the rightmost digit of N^N.
[align=left]Sample Input[/align]
2 3 4
[align=left]Sample Output[/align]
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.
刚看到题的时候就应该意识到,一定不能强行计算 N^N%10 然后输出,计算量大,而且会数据溢出;
大数乘法在这里也不太合适,毕竟要算N次方,就算计算出来,submit 的时候也不能够保证不超时;
所以感觉到应该是有内在规律,仔细研究后发现:
1.
在计算 N^N 的个位数的时候,个位数的数值仅与N的个位数有关;
所以可以利用计算( N%10 )^N 的个位数来代替原题;
2.
进一步的,演算后发现1-9的N( N>0 )次方按4个数一循环;
例:3的1-9次方的个位数依次为 ( 3, 9,7,1,3,9,7,1,3) ;
所以对于次方数也可以做简化,次方为:N%4 ;
这里要注意,当N%4==0的时候N应当取4;( 否则X^0=1,只会输出1 )
通过以上的分析,我们就将问题转化为求 ( N%10 )^( N%4 )的个位数的问题了;
大大简化了计算过程,而且保证了数据一定不会溢出;
AC代码:
<span style="font-size:18px;">#include<stdio.h> #include<math.h> int main() { int t; scanf("%d",&t); while(t--) { int n,num,index; scanf("%d",&n); num=n%10; index=n%4; if(index==0) index=4; printf("%d\n",(int)(pow((double)num,index))%10); } return 0; }</span>
注意:pow函数的格式pow( double x, int index ),要学会利用类型的强制转换;
见网上也有许多人在说用快速幂的方法也可以做;
这里仅介绍快速幂算法,不推荐在这道题上使用快速幂的方法;
快速幂:
分为二分法和位运算( 位操作 );
原理:
例如在计算 2^4 的时候,当计算过 2^2后, 可以直接计算 ( 2^2 )^2即可;
1.二分法:
<span style="font-size:18px;">#include<stdio.h> int pow2(int a,int b)// a:底数 b:指数 { int r=1,base=a; while(b!=0) { if(b%2) r*=base; // 如果次方为奇数,r乘一个底数( 使次方变为偶数 ); base*=base; // 每计算循环一次,底数所乘的数都为上一次的平方倍,减少次数; b/=2; } return r; } int main() { int a,b; while (scanf("%d%d",&a,&b)) printf("%d\n",pow2(a,b)); }</span>
2.位运算:
原理和二分法相似,只不过是通过位运算来对数据做处理的;
<span style="font-size:18px;">#include<stdio.h> int pow3(int a,int b) { int r=1,base=a; while(b!=0) { if(b&1) r*=base; base*=base; b>>=1; } return r; } int main() { int a,b; while (scanf("%d%d",&a,&b)) printf("%d\n",pow3(a,b)); }</span>
我们也可以用计算快速幂的方法来进行余数的计算( 求个位数即对10取余 ):
这里用到的方法为:
快速幂取模算法:
利用离散数学之中所讲的知识,我们有公式:
( a^b ) mod c=( a mod c )^b mod c ;
通过数学知识,我们可化简此等式有( 可循环[ 递归 ]计算 ):
奇数时:(a mod c) * ( a^2 mod c)^( b/2 ) mod c ;
偶数时: a^2 mod c)^( b/2 ) mod c ;
所以在计算 N^N 的个位数的时候,解决了 N^N可能太大存不下的问题,也减少了步数:
<span style="font-size:18px;">#include<stdio.h> int powermod(int a, int b, int c) { int rest=1; a=a%c;//公式中的( a mod c ) while(b>0)//类似于二分法分步求余 { if(b%2==1) rest=(rest*a)%c; b=b/2; a=(a*a)%c; } return rest; } int main() { int base,index,rest; while(scanf("%d%d%d",&base,&index,&rest)) printf("%d\n",powermod(base,index,rest)); }</span>
函数用于
a^b%c 的快速计算 ;
相关文章推荐
- 1.9-tr和split命令
- linux内核分析笔记----中断和中断处理程序
- 论软件的模块化与架构
- 欢迎使用CSDN-markdown编辑器
- 1.8-uniq和tee
- Android学习笔记---Matrix矩阵
- Android TextView的各种属性
- C 的 "%s"对应以'\0'结尾的字符串
- Http状态消息
- The Unique MST
- 用shell 实现对MySQL数据库分页
- WebDeveloper面试题
- Session 和Cookie的区别
- [PCA]主成分分析算法
- 从有序队列构造平衡二叉树
- iOS8扩展插件开发配置
- 组合数
- Struts2 - Interceptor中取得ActionName、Namespace、Method
- hdu1087
- ACM Computer Factory - poj 3436 (最大流)