Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Банк олимпиадных заданий.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
374.86 Кб
Скачать

Тема 2: Алгоритмы поиска и сортировки

«Забавный конфуз»

Банкир использовал для шифровки кодов от сейфа– следующий алгоритм:

На листике он случайным образом записивал ряд чисел А, состоящий из N элементов А1….Аn. Далее находил его максимальное и минимальное значение (max_a и min_a соответственно). После чего находил сумму элементов ряда S и заменял каждый элемент ряда на разницу суммы S и этого элемента Аi=S-Ai, 1≤N≤N. Кодом являлась разница максимального и минимального элемента в ряду, преобразованом К число раз.

Напишите программу, которая поможет банкиру быстро сгенирировать код.

Входные данные: Confuse.dat. Первая строка входного файла CONFUSE.DAT содержит целые числа N и K, где N - количество элементов в ряду чисел А (2 < N < 10000), а K - количество применений алгоритма кодировки к начальному ряду чисел A, 1 < K < 100. Вторая строка файла содержит N элементов ряда чисел А. Элементы ряда А - целые числа, принадлежащие диапазону от -2 000 000 000 до 2 000 000 000.

Выходные данные: Confuse.sol. Единственная строка выходного файла CONFUSE.SOL должна содержать целое число, которое есть разностью max_А и min_А.

Confuse.dat

Confuse.sol

4 2

45 52 47 46

7

{легкость решения состоит в том, что при таком изменении элементов массива, независимо от количества преобразований, разница между максимальным и минимальным элементом – остается неизменной. Решение задачи сводится к поиску максимального и минимального значения массива. Так же можно упростить задачу, считывая элементы массива из файла непосредственно}

var

max, min, x: longint;{ переменные для хранения максимального, минимального элемента и элемента массива.}

k,n,i: integer; {k – количество изменений элементов массива, n - количество элементов в массиве}

begin

{особенности чтени/записи связаны с типами входных и выходных файлов}

assign(Input, 'Confuse.dat'); {связываем файл и файловую переменную. Такой способ (без объявления переменной Input) не работает в PascalABC}

reset(Input);// открываем файл для чтения

readln(n, k); // считываем n и k

max:=-2000000000; {считаем в качестве максимального минимальный элемент диапазона}

min:=2000000000;{считаем в качестве минимального максимальный элемент диапазона}

for i:=1 to n do {цикл для просмотра элементов массива}

begin

read(x); // считываем i-ый элемент массива

if x>Max then Max:=x; {если найден элемент больший максимального – считаем его максимальным}

if x<Min then Min:=x; {если найден элемент меньший минимального – считаем его минимальным}

end;

assign(Output,'Confuse.sol');{связываем выходной файл и файловую переменную}

rewrite(Output);// открываем файл для записи

writeln(Max-Min); //выводим результат в файл

{закрываем открытые файлы}

close(input);

close(output);

end.

Тема 3: Аналитическая геометрия

«Газон»

Фермер Иван с юности следит за своим газоном. Газон можно считать плоскостью, на которой в каждой точке с целыми координатами растет один пучок травы.

В одно из воскресений Иван воспользовался газонокосилкой и постриг некоторый прямоугольный участок газона. Стороны этого участка параллельны осям координат, а две противоположные вершины расположены в точках (x1, y1) и (x2, y2). Следует отметить, что пучки травы, находящиеся на границе этого прямоугольника, также были пострижены.

Довольный результатом Иван купил и установил на газоне дождевальную установку. Она была размещена в точке с координатами (x3, y3) и имела радиус действия струи r. Таким образом, установка начала поливать все пучки, расстояние от которых до точки (x3, y3) не превышало r.

Все было хорошо, но Ивана заинтересовал следующий вопрос: сколько пучков травы оказалось и пострижено, и полито в это воскресенье?

Требуется написать программу, которая позволит дать ответ на вопрос Ивана.

Входные данные: lawn.in. В первой строке входного файла содержатся четыре целых числа x1, y1, x2, y2 (−100 000 ≤ x1 < x2 ≤ 100 000; −100 000 ≤ y1 < y2 ≤ 100 000).

Во второй строке входного файла содержатся три целых числа x3, y3, r (−100 000 ≤ x3, y3 ≤ 100 000; 1 ≤ r ≤ 100 000)

Выходные данные: lawn.out. В выходной файл необходимо вывести одно целое число — число пучков травы, которые были и пострижены, и политы.

Пример входных и выходных данных

lawn.in

lawn.out

0 0 5 4 4 0 3

14

{Одно из возможных решений данной задачи заключается в следующем. Для каждой прямой, содержащей все пучки травы с равной координатой по оси абсцисс (аналогично можно рассматривать и ось ординат), найдем ее точки пересечения с окружностью, отображающей область действия поливальной установки, если, конечно, такие точки существуют. Получив данные точки, не сложно посчитать количество пучков травы на данной прямой одновременно и политых, и постриженных. Далее, просуммировав найденные числа для всех прямых, можно найти ответ на поставленную задачу.}

var

x1,y1,x2,y2,x3,y3,x: longint;

k,r,y : longint;

input,output: text;

{функция определяет количество пучков травы, которые политы и подстрижены в исследуемом ряду}

function kol(x,z1,z2:longint):longint;

var

min,max,k: longint;

begin

if (x<x1)or(x>x2)or(z1>y2)or(z2<y1) then {ряд не пересекает подстриженную область}

k:=0 {количество политых и подстриженных пучков равно 0}

else {иначе}

begin

{определяем минимальную координату Y пучка травы, который полит}

min:=y1;

if z1>y1 then

min:=z1;

{определяем максимальную координату Y пучка травы, который полит}

max:=y2;

if z2<y2 then

max:=z2;

k:=max-min+1 {считаем количество политых пучков травы в, принадлежащих подстриженной области}

end;

kol:=k

end;

begin

{связываем файловые переменные и файлы, открываем для чтения и записи}

assign(input, 'lawn.in');

reset(input);

assign(output, 'lawn.out');

rewrite(output);

{считываем координаты вершин прямоугольной области}

readln(input,x1,y1,x2,y2);

{считываем координаты центра области полива и радиус полива}

read(input,x3,y3,r);

k:=kol(x3,y3-r,y3+r); {определяем, количество подстриженных и политых пучков травы в вертикальном ряду, проходящем через центр площади полива}

y:=r;

for x:=1 to r-1 do {пересчет всех вертикальных рядов, которые вмещаются на территорию от края до центра площади полива (не включая центральный ряд)}

begin

while sqr(x)+sqr(y)>sqr(r) do {определяется граничная точка y, принадлежащая площади полива}

y:=y-1;

k:=k+kol(x3+x,y3-y,y3+y)+kol(x3-x,y3-y,y3+y);{считается количество постриженых и политых пучков травы в рядах влево и вправо от центра полива}

end;

k:=k+kol(x3+r,y3,y3)+kol(x3-r,y3,y3);{считается количество постриженных и политых пучков травы в рядах, который проходят по касательной к площади полива}

write(output,k); {запись результата в файл}

close(input);

close(output);

end.