hdoj Last non-zero Digit in N! 【数论】

找规律!

求N!最后非0位的值。比方2是120的最后一个不是0的值。
输入N比較大,要大数保存。
注意到最后0的个数是与5的因数的个数相等。设f(n)为n!的最后非0位。
那么f(n)=((n%5)!* f(n/5) *2^(n/5))%10
因数2的个数始终大于5,从1開始每连续5个划分为1组,当中5的倍数仅仅提取出一个因数5后,
组成一个新的数列1到n/5,我们有1*2*3*4*5=6*7*8*9*5=2(取最后一个非0位),这里就是2^(n/5)。
再乘上剩下来的几个数字就可以
(比方n是123,那么第一次会剩下121,122,123三个数没有被分配)。

比如:23 就能够变为 f(23) = ((3)! * f(4) * 2^(4))%10; f(4) = 4;

故f(23) = 4; 參考http://blog.csdn.net/yihuikang/article/details/7721875

Last non-zero Digit in N!

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


Problem Description
The expression N!, read as "N factorial," denotes the product of the first N positive integers, where N is nonnegative. So, for example,
N N!
0 1
1 1
2 2
3 6
4 24
5 120
10 3628800

For this problem, you are to write a program that can compute the last non-zero digit of the factorial for N. For example, if your program is asked to compute the last nonzero digit of 5!, your program should produce "2" because 5! = 120, and 2 is the last nonzero digit of 120.
 

Input
Input to the program is a series of nonnegative integers, each on its own line with no other letters, digits or spaces. For each integer N, you should read the value and compute the last nonzero digit of N!.

Output
For each integer input, the program should print exactly one line of output containing the single last non-zero digit of N!.
 

Sample Input
 
    
1 2 26 125 3125 9999
 

Sample Output
 
    
1 2 4 8 2 8
 


 
#include<stdio.h>
#include<string.h>
const int di[4] = { 6, 2, 4, 8};//这是2的次幂最后一位的循环;
const int pre[10] = { 1, 1, 2, 6, 4,2,2,4,2,8};//前十个数的最后一位; 
int a[200], ls;
char s[200];
void tran( int ls )//转换 将个位放在a[0]处 
{
	for( int i =ls-1; i >= 0; i -- )
	a[ls-i-1] = s[i]-'0';
}
void mult(  )
{
	int i, t=0;//t是借位; 
	for( i = ls-1; i >= 0; i -- )
	{
		int q = t*10+a[i];
		a[i] = q/5;
		t = q%5;
	}
	while( ls > 0&&a[ls-1] == 0 ) --ls;//排除后面的0 细致考虑一下
}
int la_no_num( )
{
	if( ls == 1 ) return pre[a[0]]; //假设仅仅有一位直接输出或返回
	int x1 = pre[a[0]%5];   //这是f(n%5)
	mult( );
	int x2 = di[(a[0]+a[1]*10)%4];//这是2^(n/5) 为什么仅仅算前两位(提示:同余定理)
	int ans = (x1*x2*la_no_num())%10;//f(n)=((n%5)!* f(n/5) *2^(n/5))%10
	return ans;
}
int main()
{
	int la, i;
	while( ~scanf( "%s", s ) )
	{
		ls = strlen(s);
		tran(ls);	
		printf( "%d\n", la_no_num() );
	}
	
} 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值