Дано натуральное число n (1< n <109). Определить, на сколько нулей оканчивается n!
Если мы будем вычислять n!, то эту задачу сумеем решить только максимально до n=20 (смотри предыдущую задачу). Значит надо придумать какой-то другой алгоритм – без вычисления самого n! Мы знаем (!?), что любое число можно представить произведением простых делителей (смотри задачу 2.17). Например; 96=2^5*3, 19819800 = 2^3*3^2*5^2*7*11^2*13. Представим n! как произведение простых множителей. n! = 2^n2*3^n3*5^n5*7^n7…. Как по вашему, здесь больше 2-ек и 5-ок? То есть, что больше n2 или n5? Конечно 2-ек. Ведь в представлении n! = 1*2*3*4*5*6*7*8*9*10*11*12*…каждое второе число, начиная с 2, делится на 2 и только каждое 5-ое делится на 5. Значит 5-ок меньше , чем 2-ек. 0 в конце числа появляется, когда 2 умножается на 5, и количество 0-ей будет столько, сколько существует пар множителей 2 и 5. Но 5-ок меньше, чем 2-ек, и получается, что количество 0-ей в числе n! равно количеству 5-ок в разложении n! на простые множители, то есть числу n5. А теперь подсчитаем это число. В произведении n! = 1*2*3*4*5*6*7*8*9*10*11*12*… *n 5 появляется через 5 чисел и количество вхождений равно n div 5. В 25, 50 … 5 входит уже 2 раза и таких вхождений будет n div 25. В 125 … 5 входит 3 раза и таких вхождений будет n div 125 и так далее (делим на степени числа 5). Вот и весь алгоритм. Давайте вручную подсчитаем сколько в конце нулей в числе 1000! s = (1000 div 5) + (1000 div 25) +(1000 div 125) + (1000 div 625) =249. Число 1000! оканчивается на 249 нулей. В нашей программе мы так и поступаем: s:=s + (n div p); (строка 10) выполняется до тех пор степень 4 (p:=p*5; строка 11) будет меньше самого числа n.
1
2
3
4
5
6
7
8
10
11
12
13
14
15
16
17
18
|
Program A2_23;
Var
p, s,n:integer;
BEGIN
readln(n);
p:=5; s:=0;
while (p<=n) do
begin
s:=s + (n div p);
p:=p*5;
end;
writeln(s);
readln;
END.
|
//Program A2.23;
#include <iostream>
using namespace std;
int main()
{
int p=5,s=0,n;
cin>>n;
while(p<=n)
{
s=s+n/p;
p=p*5;
}
cout<<s<<endl;
return 0;
}
|
|