Вы находитесь на странице: 1из 6

Разбор задач тренировки № 9

A. Строки в книге
(Время - 1 сек., память - 16 Мб)
В книге на одной странице помещается k строк. Таким образом, на 1-й
странице печатаются строки с 1-й по k-ю, на второй — с (k+1)-й по (2∙k)-ю и т.д.
Напишите программу, которая по номеру строки в тексте определяет номер
страницы, на которой будет напечатана эта строка, и порядковый номер этой
строки на странице.
Входные данные
В единственной строке входного файла input.txt записаны два числа: k —
количество строк, которое печатается на странице, и n — номер строки
(1≤ k ≤ 200, 1≤ n ≤ 20000).
Выходные данные
В единственную строку выходного файла output.txt нужно вывести два числа
— номер страницы, на которой будет напечатана эта строка, и номер строки на
странице.
Примеры
№ input.txt output.txt
1 50 1 1 1
2 20 25 2 5
3 14 41 3 13
Разбор
Сделаем такое схематичное изображение первых двух страниц книги
Нумерац
Нумераци
Заданная Заданная ия,
я,
нумераци 1-я страница нумераци увеличен 2-я страница
увеличенн
я строк я строк ная на k-
ая на k-1
1
1 k k+1 2k …
2 k+1 k+2 2k+1
3 k+2 k+3 2k+2
… … … …
k k+k-1 2k 2k+k-1
Отсюда видно, что поделив нацело на k число из увеличенного на k-1
заданного номера строки, будем получать номер страницы. Аналогично можно
убедиться в том, что если от номера строки убрать единицу, взять остаток от
деления на k, а потом увеличить на единицу, то будем получать номер строки на
соответствующей странице.
Программа на Паскале
var
k, n : integer;
begin
assign(input,'input.txt'); reset(input);
assign(output,'output.txt'); rewrite(output);
read(k,n);
write((n+k-1)div k,' ',(n-1)mod k+1);
close(output)
end.
B. Строительство школы
(Время: 1 сек. Память: 16 Мб)
В деревне Интернетовка все дома расположены вдоль одной улицы по одну
сторону от нее. По другую сторону от этой улицы пока ничего нет, но скоро все
будет – школы, магазины, кинотеатры и т.д.
Для начала в этой деревне решили построить школу. Место для
строительства школы решили выбрать так, чтобы суммарное расстояние, которое
проезжают ученики от своих домов до школы, было минимально.
План деревни можно представить в виде прямой, в некоторых
целочисленных точках которой находятся дома учеников. Школу также
разрешается строить только в целочисленной точке этой прямой (в том числе
разрешается строить школу в точке, где расположен один из домов – ведь школа
будет расположена с другой стороны улицы).
Напишите программу, которая по известным координатам домов учеников
поможет определить координаты места строительства школы.
Входные данные
В первой строке входного файла input.txt сначала записано число N —
количество учеников (1  N  100000). Во второй строке записаны в строго
возрастающем порядке координаты домов учеников — целые числа, не
превосходящие 2∙109 по модулю.
Выходные данные
В единственную строку выходного файла output.txt нужно вывести одно
целое число — координату точки, в которой лучше всего построить школу. Если
ответов несколько, выведите наибольший из них.
Примеры
№ input.txt output.txt
1 4 3
1 2 3 4
2 3 0
-1 0 1
Разбор
Интуитивно ясно, что школу надо строить напротив одного из средних
домов. Этот факт можно доказать и строго математически, но на олимпиаде этого
и не требуется. Пусть это будет дом с номером m, тогда суммарное расстояние
равно сумме по всем домам величин xi-xm (абсолютных величин разности
координат домов). Вычисление суммарного расстояния для всех домов по этой
формуле и выбор из них минимального потребует порядка N2 действий. При
N=105 потребуется 1010 действий, т.е. 10 миллиардов. Поэтому рассмотрим другой
алгоритм.
Если школу построить напротив первого дома, то суммарное расстояние
будет равно y1=x2-x1+x3-x1+…xN-x1. Если же школу строить напротив второго
дома, то по сравнению с предыдущим случаем суммарное расстояние увеличится
от первого дома на x2-x1 и уменьшится на эту же величину для всех остальных
домов, которых N-1. Т.е. y2=y1+x2-x1-(N-1)(x2-x1)=y1+(2-N)(x2-x1). Зная yi,
аналогично легко находим yi+1. В этом случае суммарное расстояние
увеличивается для первых i домов на величину xi+1-xi и уменьшается на эту же
величину для N-i домов, т.е. yi+1=yi+(2i-N)(xi+1-xi). Из всех yi осталось выбрать
минимальное (если таких несколько, то самое правое их них). Для вычисления y1
требуется порядка N действий, при вычислении yi+1 через yi надо сделать два
вычитания и два умножения. Таким образом, в этом алгоритме требуется порядка
N действий. Также заметим, что суммарное расстояние при заданных
ограничениях задачи может не поместиться в тип longint и требуется использовать
тип int64.
Последняя выведенная формула подсказывает ещё более простое решение,
которое представлено во второй из привёденных ниже программ.
Программа
var
n, i, xmin, d : longint;
y, min : int64;
x : array [1..100000] of longint;
begin
assign(input,'input.txt'); reset(input);
assign(output,'output.txt'); rewrite(output);
read(n); y:=0;
for i:=1 to n do begin
read(d); x[i]:=d; y:=y+d-x[1]
end;
min:=y; xmin:=x[1];
for i:=1 to n-1 do begin
y:=y+(2*i-n)*(x[i+1]-x[i]);
if y<=min then begin min:=y; xmin:=x[i+1] end
end;
write(xmin); close(output)
end.
var
n, i, x : longint;
begin
assign(input,'input.txt'); reset(input);
assign(output,'output.txt'); rewrite(output);
read(n); n:=n div 2+1;
for i:=1 to n do read(x);
write(x); close(output)
end.

C. Вирусы
(Время - 2 сек., память - 16 Мб)
Для моделирования различных объектов часто применяются так называемые
клеточные поля. В простейшем случае – это прямоугольные таблицы,
характеризующие некоторую область, а в каждой ячейке таблицы записывается
какая-либо информация об исследуемом объекте. В биологии для моделирования
распространения вирусов на плоской области в каждой ячейке помечается
наличие вируса, а его распространение осуществляется в соседние ячейки по
вертикали и горизонтали за одну единицу времени. В начальный момент времени
в исследуемую область проникли несколько вирусов. Напишите программу,
которая найдёт время заражения всей исследуемой прямоугольной области.
Входные данные
В первой строке входного файла input.txt записаны два натуральных числа n и
m - размеры таблицы (количество строк и столбцов соответственно). Известно,
что 1  n, m  3000. Во второй строке вначале записано одно число k – количество
проникших вирусов, а далее записаны 2k чисел – номера строк и столбцов первых
заражённых ячеек xi, yi (1  k  10, 1  xi  n, 1  yi  m).
Выходные данные
В единственную строку выходного файла output.txt нужно вывести одно
число – время заражения всей области.
Пример
№ input.txt output.txt
1 4 5 4
2 2 1 4 5
Пояснения
В приведённом примере таблица имеет размер 4*5, в ней символом ‘V’
помечены проникшие вирусы. Легко посчитать, что за четыре единицы времени
произойдёт заражение всей области.

V
Разбор
Для каждой ячейки перебором по всем вирусам найдем минимальное время
для её заражения. Перебрав все ячейки найдем максимум из найденных
минимумов. Время заражения ячейки легко определяется так называемым
манхэттенским расстоянием – суммой модулей разностей координат ячейки и
вируса.
Программа на Паскале
var
n, m, i, j, k, l, min, d, max : integer;
x, y : array [1..10] of integer;
begin
assign(input,'input.txt'); reset(input);
assign(output,'output.txt'); rewrite(output);
read(n,m); read(k);
for l:=1 to k do read(x[l],y[l]);
max:=0;
for i:=1 to n do for j:=1 to m do begin
min:=n+m;
for l:=1 to k do begin
d:= abs(i-x[l])+abs(j-y[l]);
if d<min then min:=d
end;
if min>max then max:=min
end;
write(max);
close(output)
end.

D. Бессмыслица
(Время: 1 сек. Память: 16 Мб)
Никифор утверждал, что бессмыслица, повторенная много раз, становится
истиной. Для доказательства этого он применил следующую процедуру:
переставил на клавиатуре своего компьютера клавиши в произвольном порядке и
набрал некоторый текст. Получилась, естественно, бессмыслица. Он и эту
бессмыслицу набрал на том же компьютере с той же подправленной клавиатурой.
Новую бессмыслицу Никифор набрал еще раз и так далее – времени-то у него
много.
Требуется написать программу, которая найдет максимальное количество
шагов его процедуры, чтобы получился исходный текст.
Входные данные
В единственной строке входного файла input.txt записано одно целое число N
(1 < N < 60) – количество клавиш на клавиатуре компьютера Никифора.
Выходные данные
В единственную строку выходного файла output.txt нужно вывести одно
целое число – максимальное количество шагов проделанной Никифором
процедуры.
Пример
№ input.txt output.txt
1 4 4
2 5 6
Разбор
Рассмотрим случай N=5. Если клавиши переставить сдвигом на одну, то
после пяти наборов текста получил исходный текст. Если клавиши разбить на две
группы по три и две клавиши и в каждой группе клавиши сдвинуть на одну, после
6 наборов получим исходный текст. Таким образом, имеем, что если
N=a1+a2+…+ak, где все ai>0, то количество наборов текста равно наименьшему
общему кратному величин a1, a2, …, ak. Рассмотрев все возможные разложения,
найдем максимум из наименьших общих кратных. Это и будет ответом.
Для получения всех разложений воспользуемся алгоритмом из книги
В. Липского «Комбинаторика для программистов» (стр. 54-58).
Программа
var
n, d, l, sum, i : integer;
S, R : array [1..80] of integer;
Res, Res1 : longint;
function NOD(a,b:longint):longint;
var c : longint;
begin
while b>0 do
begin c:=a mod b; a:=b; b:=c end;
NOD:=a
end;
function NOK(a,b:longint):longint;
begin
NOK:=a*b div NOD(a,b)
end;
begin
assign(input,'input.txt'); reset(input);
assign(output,'output.txt'); rewrite(output);
read(n); S[1]:=n; R[1]:=1; d:=1; Res:=n;
while S[1]>1 do
begin
sum:=0;
if S[d]=1 Then begin sum:=sum+R[d]; d:=d-1 end;
sum:=sum+S[d]; R[d]:=R[d]-1; l:=S[d]-1;
if R[d]>0 then d:=d+1;
S[d]:=l; R[d]:=sum div l; l:=sum mod l;
if l<>0 then begin d:=d+1; S[d]:=l; R[d]:=1 end;
Res1:=S[1];
for i:=2 to d do
Res1:=NOK(Res1,S[i]);
if Res1>Res then Res:=Res1
end;
write(Res); close(output)
end.

Оценить