Записи теоретических кусков

Арифметика

Проверка на простоту

Рассмотрим множество натуральных чисел (с нулём) $\{0,\,1,\,2,\,3,\,\ldots\}$. В дальйнейшем под числами будем понимать именно натуральные числа (с нулём). Говорят, что число $n$ делится на число $d$, если найдётся такое число $k$, что $n = kd$. Число $n \ge 2$ называется простым, если оно делится только на само себя и на $1$. В противном случае число $n \ge 2$ называется составным.

Рассмотрим следующую задачу. На вход программе подаётся число $n \ge 2$. Требуется вывести prime, если оно является простым, и composite, если оно является составным.

Эту задачу можно решать, действую «по определению». Это означает, что мы явно проверим, на сколько чисел от $1$ до $n$ делится число $n$. Если делителей окажется ровно $2$, то перед нами простое число, а иначе — составное.

Приведём соответствующий код.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
var
  n, num_divisors, i: integer;

begin
  read(n);
  num_divisors := 0; // количество делителей
  
  for i := 1 to n do 
    if n mod i = 0 then
      num_divisors := num_divisors + 1;
  
  if num_divisors = 2 then
    writeln('prime')
  else
    writeln('composite');
end.

Нетрудно понять, что наш алгоритм совершает порядка $n$ действий. Как говорят программисты, наш алгоритм работает за $O(n)$.

Оказывается, что можно существенно уменьшить количество действий, необходимых для проверки числа на простоту.

Теорема. Если число $n$ является составным, то у него имеется делитель $d$ такой, что $2 \le d \le \sqrt{n}$.

Доказательство. Предположим, что утверждение теоремы неверно. Это значит, что есть такое составное число $n$, все делители которого не лежат среди чисел $2,\,3,\,\ldots,\,\sqrt{n}$. Поскольку число $n$ составное, то найдутся такие $a$ и $b$, что $n = ab$. По предположению, $a \gt \sqrt{n}$ и $b \gt \sqrt{n}$, откуда $ab \gt \sqrt{n} \cdot \sqrt{n}$, т. е. $ab \gt n$. Мы пришли к противоречию.

Доказанная нами теорема позволяет вести цикл в строке 8 нашего алгоритма от 2 до $\sqrt{n}$. Таким образом, время работы нашего оптимизированного алгоритма составит $O(\sqrt{n})$, что позволит быстро проверять на простоту числа порядка $10^{16}$. Напомним, что для хранения таких чисел в Паскале следует использовать тип int64, а в C++ — long long.

Алгоритм Евклида

Определение. Число $d$ называется наибольшим общим делителем двух чисел $a$ и $b$, если $d$ делит $a$ и $b$, причём является наибольшим из подобных чисел. Обычно пишут $d = $ НОД$(a, b)$.

Пример: