首页 > 代码库 > ACM-简单题之Factorial——poj1401
ACM-简单题之Factorial——poj1401
Time Limit: 1500MS | Memory Limit: 65536K | |
Total Submissions: 13993 | Accepted: 8678 |
Description
ACM technicians faced a very interesting problem recently. Given a set of BTSes to visit, they needed to find the shortest path to visit all of the given points and return back to the central company building. Programmers have spent several months studying this problem but with no results. They were unable to find the solution fast enough. After a long time, one of the programmers found this problem in a conference article. Unfortunately, he found that the problem is so called "Travelling Salesman Problem" and it is very hard to solve. If we have N BTSes to be visited, we can visit them in any order, giving us N! possibilities to examine. The function expressing that number is called factorial and can be computed as a product 1.2.3.4....N. The number is very high even for a relatively small N.
The programmers understood they had no chance to solve the problem. But because they have already received the research grant from the government, they needed to continue with their studies and produce at least some results. So they started to study behaviour of the factorial function.
For example, they defined the function Z. For any positive integer N, Z(N) is the number of zeros at the end of the decimal form of number N!. They noticed that this function never decreases. If we have two numbers N1 < N2, then Z(N1) <= Z(N2). It is because we can never "lose" any trailing zero by multiplying by any positive number. We can only get new and new zeros. The function Z is very interesting, so we need a computer program that can determine its value efficiently.
Input
Output
Sample Input
6 3 60 100 1024 23456 8735373
Sample Output
0 14 24 253 5861 2183837
题目:http://poj.org/problem?id=1401
题目是求N!中末尾0的个数。
这道题,是我以前在经典例题100道中看到的,做出来的,但是,发现理解错了。(感谢一位网友的提醒啊!)
所以,重新做一下,发现poj上有这道题,正好可以拿来测试一下做的是否正确。
这道题做法,显然不能求出来阶乘再数0的个数。
所以,要换一个思路。
为什么会产生0呢?源于2x5,于是可以通过数有多少个(2,5)因子对来判断有多少个0.
我们又可以发现,5的个数永远会大于2的个数。
又可以简化为数5的个数来做。
当时,还很年轻,做法让现在的我看,有点纠结啊。。
当时做的是,从1到N(所输入的数)循环,看看能不能被5整除,若能整除,继续除5,直到不能整除为止。
这个做法显然答案正确,但是在这道题里,TLE必须的。。。
#include <stdio.h> int main() { int i,N,k,t; double num; bool prime; scanf("%d",&t); while( t-- ) { scanf("%d",&N); k=0; for(i=1;i<=N;i++) //查看有多少个5 { num=i/5.0; if(num-int(num)==0) prime=true; else prime=false; while(num>=1&&prime==true) { num/=5.0; if(num-int(num)==0) prime=true; else prime=false; k+=1; } } printf("%d\n",k); } return 0; }
然后,现在想想,这道题,不需要这么麻烦啊。
数5的倍数,就可以了。
以698为例:
698/5=139.6→取整→139 (表示有139个数为5的倍数) sum=sum+139 (sum初始化为0)
139/5=27.8 →取整→27 (表示有27个数为25的倍数)sum=sum+27
(为什么25的倍数,只加了一遍,不应该加 27*2的吗,25表示两个5?
因为,25的之前有一个5,在第一遍139个里面算过一次了,所以不需要加两遍。)
27/5=5.4 → 取整→5 (表示有5个数为125的倍数)sum=sum+5
5/5=1 → 取整 → 1 (表示有1个数为625的倍数) sum=sum+1
1/5=0 结束。
所以答案是 139+27+5+1=172
恩,所以程序,就很简单了:
/************************************** *************************************** * Author:Tree * *From :http://blog.csdn.net/lttree * * Title : Factorial * *Source: poj 1401 * * Hint : N!求0的个数 * *************************************** **************************************/ // scanf 125MS, cin 422MS #include <stdio.h> int main() { // sum为答案,存储每次除5后的数(累加) int t,n,sum; scanf("%d",&t); while( t-- ) { sum=0; scanf("%d",&n); while( n ) { n/=5; sum+=n; } printf("%d\n",sum); } return 0; }