POJ 1401 Factorial 试着分析一下数学问题
【简单题,试着分析一下,发现自己表达能力不够好哈】
题意:给一个数N,计算N!末尾有几个0。
因为这道题出现在动态规划的作业中,一开始也尝试着去DP了下。结果案例总是通不过。DP功力还不够。
看来,还要用做数学题的办法试试。
如果使末尾多一个0,那么这个可以由2 * 5得到;
如果末尾多两个0,可以由4 * 25得到;
推广:
末尾0的个数 等式 等式左边 等式右边
1 2 * 5 2^1 5^1
2 4 * 25 2^2 5^2
3 8 * 125 2^3 5^3
... ... ... ...
n 2^n 5^n
又发现,对一个数N,定义s(x)表示x!末尾0的个数
所以s(N!) = (N / 5^1) + (N / 5^2) + (N / 5^3) + ...
优化:
当5^i > N时,商为0。当循环进行到5^i > N时,就可以终止了。
又给出数据最大为10^9,log(5^13) > 9。所以对于每个数最多只需计算12次。
得到算法。
代码:
1 #include <iostream>
2 using namespace std;
3
4 int num[15];
5
6 void init()
7 {
8 num[0] = 1;
9 for(int i = 1; i <= 13; i++)
10 num[i] = num[i-1] * 5;
11 }
12
13 int main()
14 {
15 int t;
16 init();
17 scanf("%d", &t);
18 while (t--)
19 {
20 int n, total = 0;
21 scanf("%d", &n);
22 for(int i = 1; i < 14 && num[i] <= n; i++)
23 total += n / num[i];
24 printf("%d\n", total);
25 }
26 return 0;
27 }