| Россия, Пошатово |
Переменные, выражения, присваивания
1.1.20.Составить программу, печатающую квадраты всех натуральных чисел от 0 до заданного натурального n.
Решение.
k:=0;
writeln (k*k);
{инвариант: k<=n, напечатаны все
квадраты до k включительно}
while not (k=n) do begin
| k:=k+1;
| writeln (k*k);
end;1.1.21. Та же задача, но разрешается использовать из арифметических операций лишь сложение и вычитание, причем общее число действий должно быть порядка n.
Решение. Введем переменную k_square (square -
квадрат), связанную с k соотношением
:
k := 0; k_square := 0;
writeln (k_square);
while not (k = n) do begin
| k := k + 1;
| {k_square = (k-1) * (k-1) = k*k - 2*k + 1}
| k_square := k_square + k + k - 1;
| writeln (k_square);
end;Замечание. Можно обойтись без вычитания с помощью такой хитрости:
while not (k = n) do begin
| k_square := k_square + k;
| {k_square = k*k + k}
| k := k + 1;
| {k_square = (k-1)*(k-1)+(k-1)=k*k-k}
| k_square := k_square + k;
end;1.1.22.
Составить программу, печатающую разложение на простые
множители заданного натурального числа
(другими словами, требуется печатать только простые числа
и произведение напечатанных чисел должно быть равно n ;
если
, печатать ничего не надо).
Решение. Вариант 1.
k := n;
{инвариант: произведение напечатанных чисел и k равно
n, напечатаны только простые числа}
while not (k = 1) do begin
| l := 2;
| {инвариант: k не имеет делителей в интервале (1,l)}
| while k mod l <> 0 do begin
| | l := l + 1;
| end;
| {l - наименьший делитель k, больший 1, следовательно,
| простой}
| writeln (l);
| k:=k div l;
end;Вариант 2.
k := n; l := 2;
{произведение k и напечатанных чисел равно n; напечатанные
числа просты; k не имеет делителей, меньших l}
while not (k = 1) do begin
| if k mod l = 0 then begin
| | {k делится на l и не имеет делителей,
| | меньших l, значит, l просто}
| | k := k div l;
| | writeln (l);
| end else begin
| | { k не делится на l }
| | l := l+1;
| end;
end;1.1.23. Составить программу решения предыдущей задачи, использующую тот факт, что составное число имеет делитель, не превосходящий квадратного корня из этого числа.
Решение. Во втором варианте решения вместо l:=l+1 можно написать
if l*l > k then begin | l:=k; end else begin | l:=l+1; end;
1.1.24.
Проверить, является ли заданное натуральное число
простым.
1.1.25.
(Для знакомых с основами алгебры) Дано целое гауссово число
(принадлежащее
).
(a) Проверить, является ли оно простым (в
).
(б) Напечатать его разложение на простые (в
)
множители.
1.1.26.Разрешим применять команды write(i) лишь при
. Составить
программу, печатающую десятичную запись заданного
натурального числа
. (Случай
явился бы некоторым исключением, так как обычно нули
в начале числа не печатаются, а для
-
печатаются.)
Решение.
base:=1;
{base - степень 10, не превосходящая n}
while 10 * base <= n do begin
| base:= base * 10;
end;
{base - максимальная степень 10, не превосходящая n}
k:=n;
{инвариант: осталось напечатать k с тем же числом
знаков, что в base; base = 100..00}
while base <> 1 do begin
| write(k div base);
| k:= k mod base;
| base:= base div 10;
end;
{base=1; осталось напечатать однозначное число k}
write(k);Типичная ошибка при решении этой задачи: неправильно
обрабатываются числа с нулями посередине. Приведенный
инвариант допускает случай, когда
; в этом
случае печатание k начинается со старших нулей.