您的位置:首页 > 其它

Num 16: HDOJ: 题目1061 : Rightmost Digit [ 求个位数 ] [ 快速幂算法 ]

2015-07-27 15:18 531 查看
题目:



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 的快速计算 ;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: