Hosted by uCoz

Задача № 19. Вывести на экран первых n простых чисел

Формулировка. Дано натуральное число n. Вывести на экран n первых простых чисел. Например, при вводе числа 10 программа должна вывести ответ: 2 3 5 7 11 13 17 19 23 29

Решение. Эта задача похожа на предыдущую тем, что здесь нам тоже необходимо проверить все натуральные числа на некотором отрезке, на этот раз используя еще один счетчик для подсчета найденных простых. Однако на этот раз мы не можем узнать, сколько придется проверить чисел, пока не насчитается n простых. Следовательно, здесь нам не подходит цикл for, так как мы не можем посчитать необходимое количество итераций.

Здесь нам поможет цикл while. Напомним, что тело цикла while повторяется до тех пор, пока остается истинным булевское выражение в его заголовке (поэтому его еще называют циклом с предусловием). Так как while не имеет переменной цикла, которая увеличивается на 1 с каждым следующим шагом, то при его использовании необходимо обеспечить изменение некоторых переменных в теле цикла, от которых зависит условие в его заголовке, таким образом, чтобы при достижении требуемого результата оно стало ложным.

Так как мы должны найти и вывести n первых простых чисел, подсчитывая их, и с каждый найденным простым числом некоторый счетчик (пусть это будет primes с начальным значением 0) увеличивается на 1, то условием в заголовке while будет выражение primes < n. Иными словами, цикл продолжается, пока число найденных чисел меньше требуемого. На последнем же шаге будет выведено последнее число, primes станет равным n и следующего шага цикла уже не будет, так как условие в его заголовке станет ложным. На этом работа программы будет закончена.

Проверяться на простоту будет некоторое число k, которое с каждой итерацией цикла обязательно будет увеличиваться на 1 (таким образом, мы будем двигаться по отрезку натуральных чисел, пока не выберем из него заданное количество простых).

Алгоритм на естественном языке:

1)      Ввод n;

2)      Обнуление переменной primes;

3)      Присваивание переменной k значения 1;

4)      Запуск цикла с предусловием primes < n. В цикле:

                                1.        Обнуление переменной count;

                                2.        Запуск цикла, при котором i изменяется от 1 до k. В цикле:

a.  Если k делится на i, то увеличиваем значение переменной count на 1;

                                3.        Если count = 2, выводим на экран число k, символ пробела и увеличиваем значение счетчика primes на 1;

                                4.        Увеличиваем значение k на 1.

Код:

  1. program FirstNPrimes;
  2. var
  3. i, k, n, count, primes: word;
  4. begin
  5. readln(n);
  6. k := 1;
  7. primes := 0;
  8. while primes < n do begin
  9. count := 0;
  10. for i := 1 to k do begin
  11. if k mod i = 0 then inc(count)
  12. end;
  13. if count = 2 then begin
  14. write(k, ' ');
  15. inc(primes)
  16. end;
  17. inc(k)
  18. end
  19. end.

Выполним ручную прокрутку алгоритма, взяв в качестве n число 2. При этом будем уже по привычке красным цветом обозначать переменные, изменившиеся после выполнения данной строки, а прочерком те, которые на данном шаге не определены, так как алгоритм до них еще «не дошел». При повторении шагов цикла итерации явно считать не будем (хотя легко увидеть, что их номерам полностью соответствует изменяющаяся после каждого очередного выполнения тела переменная k), и в таблице будет указана лишь та строка, которая выполняется. На тех шагах, на которых переменные не изменяются, будем пояснять смысл выполняющихся операторов.

Для наглядности все же отделим друг от друга четные и нечетные шаги основного цикла while, при этом его внутренний цикл будем считать самоочевидным и в строке 12-14 будем фиксировать те значения переменных, которые будут получены по выходу из него.

№ строки n k primes i count
7 2
8 2 1
9 2 1 0
10 (primes < n) = true – входим в цикл
11 2 1 0 0
12-14 2 1 0 от 1 до 1 1
15-18 (count = 2) = false
19 2 2 0 1
10 (primes < n) = true – входим в цикл
11 2 2 0 0
12-14 2 2 0 от 1 до 2 2
15 (count = 2) = true
6 Вывод числа k (то есть 2)
17-18 2 2 1 2
19 2 3 1 2
10 (primes < n) = true – входим в цикл
11 2 3 1 0
12-14 2 3 1 от 1 до 3 2
15 (count = 2) = true
16 Вывод числа k (то есть 3)
17-18 2 3 2 2
19 2 4 2 2
10 (primes < n) = false – программа завершена

Как видим, описать действия даже такого элементарного алгоритма и даже при столь малых исходных данных – достаточно трудоемкая и трудно проверяемая задача, поэтому очень важно понимать логику самой программы и уметь представлять себе целостную картину ее поведения с минимальными потребностями в моделировании.

Вычислительная сложность. Так как в данной задаче в главном цикле присутствует вложенный, в котором происходит ровно k операций (сложность этой конструкции мы определили в задаче 19), то его сложность явно не меньше O(n2) и превышает ее, так как нам явно необходимо выполнить более чем n шагов главного цикла. При этом точность расчета сложности зависит от распределения простых чисел, которое описывается с помощью достаточно сложных математических приемов и утверждений, так что мы не будем далее рассматривать эту задачу.