码迷,mamicode.com
首页 > 其他好文 > 详细

SCU - 1115 阶乘

时间:2016-08-17 21:30:25      阅读:224      评论:0      收藏:0      [点我收藏+]

标签:

题目:

N的阶乘定义为:N!=N×(N-1)×……×2×1

请编写一个程序,输出N的阶乘的十进制表示中从最末一个非0位开始,

自低位向高位数的第M位。

其中:0<=N<=10000,1<=M<=5

例如:N=5,M=2,结果是1(5!=120)  N=8,M=3,结果为0(8!=40320)

输入:

第一行一个整数K (1<=K<=100),代表测试数据的个数;

接下来K行,每行两个整数N,M

输出:

     输出K行,每行一个整数,即测试数据的结果。

样例:

输入:

2
5 2
8 3

输出:

1
0


这个题目的链接:点击打开链接

题目很简洁,但是很有意思啊。

首先,10000!太大,肯定是边乘边取模。

但是模多少呢?10000!的末尾的0的个数可是很多的,不可能先模一个很大的数,再数有多少个0。


这个题目,我认为必须先求出,n!末尾的0的个数d。

其实就是求d,使得5^d |  n! 成立但5^(d+1) |  n!不成立。

函数degree_in_fact就是专门干这个的,而且代码简单的可怕。


原理:

画一个n行n列的矩阵,第i(i从1到n)行第j(j从1到n)列表示i是否是p^j的倍数,是它的倍数就是1,不是就是0

其实远远不需要n列,但是我只是给出定理的证明,和空间效率无关。

下面考虑这个矩阵的和。

一方面,每一行的和表示的是i里面的p的次数,比如第p^3行,前面3个为1,后面的都是0,所以这一行的和为3,即p的次数。

所以矩阵的和是n!中p的次数。

另一方面,每一列的和是,从1到n有多少个数是p^j的倍数,所以答案为n/(p^j)

综上,n!中p的次数为n/p+n/(p^2)+n/(p^3)+......当j足够大时n/(p^j)=0


请注意,这个表达式是无法用递归来写的,因为这是整数的除法,不是实数的除法。

不过很巧的是,刚好有这么一个定理:

n/p^j/p=n/p^(j+1)

不要以为这个很显然,本文所有的除法都是整数的除法,也就是5/2会得到2,和实数的不同。

定理的证明:

假设右边的n/p^(j+1)=k,即k*p^(j+1)<=n<(k+1)*p^(j+1)

那么k*p<=n/p^j<(k+1)*p,那么k<=n/p^j/p<k+1

即n/p^j/p=k,证毕。


现在,表达式可以改写了,n!中p的次数为n/p+n/p/p+n/p/p/p+......

这个式子就可以用递归非常简单的写出来了。

degree_in_fact(n, 5)的值就是n!末尾的0的个数。


算出来0的个数为num之后,又要怎么做呢?

从1到n累乘,在乘之前,去掉num个2和num个5,剩下所有的数累乘,同时模100000即可。

这样就可以得到n!除掉后缀0之后的的最后5位

(这5位除了最后一位肯定不是0之外,都有可能是0,事实上还有可能都是0)

代码:

#include<iostream>
using namespace std;

int degree_in_fact(int m, int p)//求m!中素数p的次数
{
	if (m)return degree_in_fact(m / p, p) + m / p;
	return 0;
}

int main()
{
	int k, n, m;
	cin >> k;
	while (k--)
	{
		cin >> n >> m;
		int num = degree_in_fact(n, 5);
		int fact = 1;
		for (int i = 1; i <= n; i++)
		{
			int j = i;
			while (j % 2 == 0 && num)
			{
				j /= 2;
				num--;
			}
			while (j % 5 == 0)j /= 5;
			fact = fact*j % 100000;
		}
		m--;
		while (m--)fact /= 10;
		cout << fact % 10 << endl;
	}
	return 0;
}

SCU - 1115 阶乘

标签:

原文地址:http://blog.csdn.net/nameofcsdn/article/details/52232438

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!