- •Тема: Перебор вариантов. Задача 1. Замечательные числа
- •Задача 2. Острова
- •Задача 3 Клавиатура
- •Задача 4 . Вырубка деревьев
- •Краткие методические рекомендации по решению задачи
- •Оценка решения
- •Формат входных данных
- •Формат выходных данных
- •Работа с большими числами
- •Золото племени абба
- •Сортировка и поиск
- •2. Домашнее задание.
- •Метод перебора вариантов, отсечения перебора
- •Сумма двух чисел
- •Элементы вычислительной геометрии
- •4. Две окружности
- •Эффективные структуры данных
- •5. Поиск прямоугольников (Время: 0,5 сек. Память: 16 Мб Сложность: 34%)
- •Тема 1: «Работа с длинными числами»
- •Тема 2: Алгоритмы поиска и сортировки
- •Тема 3: Аналитическая геометрия
- •Тема 4: Перебор вариантов
- •Тема 5: Строки. Элементы лексического и синтаксического разобра
- •Задача 3. "Функция"
- •Ограничения
- •Площади покрытия антенны
- •Площадь покрытия решение
- •Элементы лексического и синтаксического разбора Шифровка
- •Шифровка Решение
- •Сортировка и поиск Независимые судьи
- •Независимые судьи Решение
- •Сувениры
- •Сувениры Решение
- •Треугольник Условие задачи
- •Треугольник Решение
- •Олимпиадные задачи по информатике
- •Задача 1. «Код да Винчи»
- •Задача 3 «Буквы»
- •Задача 4 «Соревнования»
- •Задача «Красивая последовательность»
- •Тема: Задача на динамическое программирование
- •Динамическое программирование Задача: Черепашка
- •Решение
- •Тема: Работа с большими числами
- •Тема: Сортировка и выбор
- •Задача. Подземная дорога (поиск в ширину)
- •Формат входных данных
- •Задача rebus
- •Задача “Эчпочмаки”
- •Задача “Ниточка”
- •Задача “Обезьяны”
- •Задача Интересное число
Треугольник Условие задачи
На плоскости даны n точек и их координаты: x1, y1, x2,y2, ….. xn, yn.
Найти наибольшую площадь треугольника по координатам трех произвольных точек плоскости. Во входном файле input.txt в первой строке дано количество точек n (натуральное число n ≤ 1000), во второй – координаты первой точки x1, y1, в третьей – x2, y2, и т. д. в n+1 строке координаты n-й точки xn, yn (координаты – действительные числа). В выходном файле output.txt содержится одно число (действительное) – площадь треугольника.
Примеры входного и выходного файлов
input.txt |
output.txt |
5 1 1 2 2 4 1 1 4 2 3 |
4.5000000000E+00 |
Треугольник Решение
s – искомая площадь, s 1 – площадь треугольника образованного тремя произвольными точками из данного множества
Массивы х и у содержат координаты точек
program ploschad;
var n, i, j, k: integer;
x: array [1..1000] of real;
y: array [1..1000] of real;
s, s1: real;
f, g: text;
begin
assign (f,’input.txt’);
assign (g,’output.txt’);
reset (f);
readln (f, n); // чтение из файла количества точек
for i:=1 to n do
readln (f, x[i], y[i]); //чтение координат точек, запись их в массив
s:=0; close (f);
for i:=1 to n do //перебор всех точек по три
for j:=2 to n do
for k:=3 to n do
begin
s1:=0.5*abs(x[i]*(y[j]-y[k])+x[j]*(y[k]-y[i])+x[k]*(y[i]-y[j])); //вычисление площади по координатам его вершин
if s1>s then s:=s1; //выбор наибольшей площади
end;
rewrite(g);
writeln(g,s); //запись в файл
close(g);
end.
Олимпиадные задачи по информатике
Хоружий А.Н., руководитель ГМО
учителей информатики г. Брянки
Задача 1
Lift. Чтобы поднять на N-й этаж M-этажного дома новый холодильник, Витя вызвал бригаду грузчиков. Оплата работы грузчиков рассчитывается так: за подъем холодильника на один этаж требуется заплатить 200 рублей, за спуск на один этаж - 100 рублей. За подъем и спуск на лифте плата не взимается. Несмотря на то, что в доме есть лифт, Вите возможно все же придется заплатить грузчикам, поскольку лифт останавливается только на каждом K-м этаже, начиная с первого (то есть на этажах с номерами 1, K +1, 2K +1, 3K +1, ...). Нужно вычислить, какой минимальной суммы денег достаточно, чтобы грузчики доставили холодильник с первого этажа на N-й.
Во входном файле записаны три числа:
M (2 <= M <= 100), N (2 <= N <= M) и K (2 <= K <= M-1), разделенные пробелами.
В выходной файл выведите одно число - минимальную стоимость подъема холодильника.
|
Файл Lift.dat |
Файл Lift.sol |
Пример 1 |
20 7 4 |
200 |
Пример 2 |
20 7 2 |
0 |
Решение на языке Паскаль:
program Lift;
var A,B,N,K,M,c,i:integer; W:array[1..20] of integer; f,f1:text;
begin
assign (f, 'Lift.dat');
rewrite(f);
write(' vvedite kol-vo etazhey M='); readln(M);
write(' vvedite etazh dostavki N='); readln(N);
write(' vvedite shag ostanovki lifta K='); readln(K);
writeln(f,M:3,N:3,K:3);
close(f);
i:=1;
repeat
W[i]:=(i-1)*k+1; c:=i;
i:=i+1;
until W[i-1]>M ; { c - chetchik ostanovok);}
For i:=1 to c do begin
if (W[i] < N) and(N < W[i+1]) then
begin A:=(N-W[i])*200;
B:=(W[i+1]-N)*100;
if A>B then begin
assign(f1, 'Lift.sol');
rewrite(f1);
writeln(' opyckaemca B=',B);
writeln(f1,B);
close(f1)
end
else begin
assign(f1, 'Lift.sol');
rewrite(f1);
writeln(' podnimaemca A=',A);
writeln(f1,A);
close(f1)
end;
end;
if W[i]=N then begin
assign(f1, 'Lift.sol');
rewrite(f1);
writeln('nichego ne platim');
writeln(f1,'nichego ne platim');
close(f1)
end;
end;
end.
Задача 2
«Несчастливые пиковые» числа. Трехзначное число назовем «пиковым», если его цифра десятков будет больше цифры единиц и сотен (напр., число 276 - «пиковое», а 954 и 277 - нет). Составьте программу, которая подсчитывает, сколько «пиковых» чисел находится на отрезке [A, B] и сколько из них делятся без остатка на 13.
Технические условия |
||||
Имя программы |
PICK.* |
|||
Ввод |
Два целых числа 100<=Ai<=Bi<=999 |
|||
Вывод |
В текстовый файл PICK.SOL выводится количество «пиковых» чисел и тех из них, которые делятся без остатка на 13 |
|||
Пример |
PICK.* |
PICK.SOL |
Объяснение |
|
1 |
135 145 |
4 1 |
В первом тесте на промежутке 135-145 находится 4 пиковых числа: 140, 141, 142, 143 и 143 делится без остатка на 13, во втором тесте числа 120 и 121 на 13 не делятся |
|
Решение на языке Паскаль:
program PICK;
var x,a,b,n,k,m,c,t:integer; f,f1:text;
begin
write(' vvedite 2 chisla cheres probel ');
assign (f, 'PICK.DAT');
rewrite(f);
readln(A,B); writeln(f,A,' ',B);
close(f);
for x:=a to B do
begin
n:=x Div 100;
k:=x mod 100 div 10;
m:=x mod 10;
if (K>n) and (k>m) then c:=c+1;
if x mod 13=0 then t:=t+1;
end;
assign(f1, 'PICK.SOL');
rewrite(f1);
writeln(f1,c,' ',t);
close(f1);
writeln(' a=',a,' b=',b,' c=',c,' t=',t);
end.
Второй вариант
Program PICK;
var f1,f2 : text; a,b,c,d,i,j,k,l,n,x,y,z : integer;
begin
assign(f1,'pick.dat');
reset(f1);
assign(f2,'pick.sol');
rewrite(f2);
readln(f1,l);
for d:= 1 to l do begin
read(f1,a,b);
k:=0;
J:=0;
for i:= a to b do begin
z:=i mod 10;
y:=i div 10 mod 10;
x:=i div 100;
if (y>x) and (y>z) then k:=k+1 ;
if (y>x) and (y>z) and (i mod 13 =0)
then j:=j+1 ;
end;
write(f2,k,' ',j);
end;
close(f1);
close(f2);
end.
Задача 3
Отрезок. Отрезок на плоскости задается двумя несовпадающие конечными точками A (x1; y1) и B (x2; y2). С точки С (х3; у3) к прямой, содержащей отрезок АВ, проводится перпендикуляр г. Определить, попадает перпендикуляр на отрезок АВ или на его продолжение.
Во входном файле содержится три пары чисел, являющихся координатами точек А, В, С. В файле содержится ответ «На отрезок» или «На продолжение».
Пример входного и выходного файлов
Файл Z1.dat |
Файл Z1.rez |
3 3 6 2 8 4 |
На продолжение |
Решение на языке Паскаль:
program z3;
var x1,x2,x3,y1,y2,y3,ac,ab,bc,a1,b1:real;f,f1:text;
begin
assign (f, 'z1.dat');
rewrite(f);
readln(x1,y1);
readln(x2,y2);
readln(x3,y3);
writeln(f,x1,y1);
writeln(f,x2,y2);
writeln(f,x3,y3);
close(f);
ac:=sqr(x1-x3)+sqr(y1-y3);
ab:=sqr(x2-x1)+sqr(y2-y1);
bc:=sqr(x3-x2)+sqr(y3-y2);
b1:=(ab+bc-ac)/(2*sqrt(ab*bc));
a1:=(ac+ab-bc)/(2*sqrt(ac*ab));
if (a1 < 0) or (b1 < 0) then
begin
assign(f1, 'z1.rez');
rewrite(f1);
writeln('na prodolzenue');
writeln(f1,'na prodolzenue');close(f1)
end
else
begin
assign(f1, 'z1.rez');
rewrite(f1);
writeln ('na otrezke');
writeln(f1,'na otrezke');
close(f1)
end
end.
Задача 4
Digit. В положительном целом числе вычеркнуть цифру так, чтобы число, которое осталось, было наибольшим.
|
Файл Digit.dat |
Файл Digit.sol |
Пример 1 |
321 |
32 |
Пример 2 |
123 |
23 |
Решение на языке Паскаль:
program Digit;
var x,a,b,c,n:integer; f,f1:text;
begin
write(' vvedite chislo ');
assign (f, 'Digit.dat');
rewrite(f);
readln(x);
writeln(f,x);
close(f);
a:=x div 100;
b:=x mod 100 div 10;
c:=x mod 10;
if (a < b) and (a < c) then N:=10*b+c else if (a > b) and (b < c) then N:=10*a+c else N:=10*a+b;
assign(f1, 'Digit.sol');
rewrite(f1);
writeln('N=',N);
writeln(f1,N);
close(f1)
end.
Задача 5
Места. В плацкартном вагоне 54 места, которые расположены в девяти купе. Места от 1 до 36 основные и они расположены по четыре в купе (1 - 4 в первом, ..., 33 - 36 в девятом), от 37 до 54 - боковые, разбиты по два, но расположение по купе обратное: места 37, 38 находятся в девятом купе, 39 и 40 в восьмом, ..., 53 и 54 в первом. По номеру места определите номер купе.
Технические условия |
|||
Имя программы |
VAGON.* |
||
Ввод |
С клавиатуры вводится целое число – номер места (от 1 до 54) |
||
Вывод |
На экран выводится целое число - номер купе |
||
Пример |
Ввод |
Вывод |
|
1 |
39 |
8 |
|
Решение на языке Паскаль:
program vagon;
var f1,f2:text; n:integer;
begin
assign(f1,'vagon.dat');
assign(f2,'vagon.sol');
reset(f1);
rewrite(f2);
readln(f1,n);
case n of
1..4,53,54:writeln(f2,'1');
5..8,52,51:writeln(f2,'2');
9..12,50,49:writeln(f2,'3');
13..16,48,47:writeln(f2,'4');
17..20,46,45:writeln(f2,'5');
21..24,44,43:writeln(f2,'6');
25..28,42,41:writeln(f2,'7');
29..32,40,39:writeln(f2,'8');
33..36,38,37:writeln(f2,'9');
end;
close(f1);
close(f2);
end.
Задача 1. Матрёшки.
Тип: сортировка массива
Сложность: средняя
На полке в магазине в ряд стоят матрешки. В каждой из них пока нет других, но существует возможность вставить одну матрешку в другую. Такая возможность существует, если разница высот составляет ровно 1 см и другая матрешка такой же высоты не находится в середине.
Задание. Напишите программу, которая поможет покупателю определить сколько матрешек можно прибрести, с учетом вложенности и какие именно матрешки необходимо для этого взять.
Входные данные. В первой строке входного файла input.dat записано количество матрешек N (1 ≤ N ≤ 10000). Во второй строке записаны N чисел, определяющих высоты соответствующих матрешек в сантиметрах. Каждое число находится в пределах от 1 до 109.
Выходные данные. В первую строку выходного файла output.dat необходимо вывести максимальное количество матрешек, которые могут быть последовательно вставлены друг в друга, а вторая строчка должна содержать номера таких матрешек в порядке увеличения высоты (если высоты матрешек повторяются, то покупатель берет первую из равновеликих, стояющих на полке).
Ограничение по времени: 0,5 секунды на тест.
Пример входных и выходных данных
input.dat |
output.dat |
10 20 3 5 3 1 7 4 2 8 10 |
5 5 8 2 7 3 |
Анализ. Входные данные состоят из двух строк. Первая - это количество матрешек в магазине, а вторая - высоты соответствующих матрешек. Тогда задача сводится к нахождению длины монотонной последовательности высот матрешек с разницей высот ровно в 1 см. Поиск такой последовательности удобно будет сделать в отсортированном массиве. Так как в результате работы программы необходимо вывести номера матрешек, которые необходимо купить, то входные данные удобно хранить в двумерном массиве, где первая компонента - это высота матрешки, а вторая - ее начальный порядковый номер на полке.
Метод поиска наибольшей монотонной последовательности заключается в проверке условия монотонности с подсчетом начала последовательности и ее длины. Самая длинная текущая последовательность сравнивается с найденной, таким образом, в конце работы получим самую длинную монотонную последовательность.
// блок объявления переменных
var mass : array [ 1..10000 , 1..2 ] of longint ;
n , i , j , mdl , tdl , n_tdl , n_mdl : integer ;
r : longint ; pr : boolean ;
input:text;
output:text;
begin
//организация связи с файлами открытие файов на запись и чтение
assign ( input, ' input.dat ' );
assign ( output, ' output.dat ' ) ;
reset ( input ) ; rewrite ( output ) ;
// чтение данных из файла
Readln(input,n) ; // количество матершек
for i :=1 to n do begin //заполнение двумерного массива
read ( input, mass [i,1 ] ); // первый столбец – высота матрешек
mass [i,2] := i ; // второй столбец – порядковый номер на полке
end;
// в блоке происходит перебор массива и исключение повторяющихся данных
for i :=1 to n-1 do
for j := i+1 to n do
if mass [ i ,1]= mass [ j , 1 ] { если встречаются повторяющиеся данные одно из значений заменяется на -1 }
then begin mass [ j ,1]:= -1;
end;
// блок сортировки массива
pr:=true ;
while pr do
begin
pr:= false ;
for i :=1 to n-1 do
if mass [ i ,1] >mass [ i +1 ,1] then
begin
r :=mass [ i , 1 ] ; mass [ i ,1]:= mass [ i +1 ,1];
mass [ i +1 ,1]:= r ; r :=mass [ i , 2 ] ;
mass [ i ,2]:= mass [ i +1 ,2]; mass [ i +1 ,2]:= r ;
pr:=true ;
end ;
end ;
// задание начальных значений переменным для подсчета максимальной длины последовательности, которая удовлетворяет условию задачи
n_tdl :=1; tdl :=1; n_mdl:=0;mdl:=0;
for i :=1 to n do
begin
//проверка условия разницы в высоте в 1 см
if mass [ i ,1]+1<>mass [ i +1 ,1]
then begin
// если текущая длина последовательности больше максимальной
if tdl>=mdl
// принимаем такущую длину за максимальную
then begin n_mdl:=n_tdl ; mdl:= tdl ; end;
// задаем значения для дальнейшей работы
tdl :=1; n_tdl:= i +1;
end
// если условие разницы в высоте не выполняется, то значение текущей длины последовательности увеличиваем на единицу
else tdl := tdl +1;
end ;
// вывод данных в файл
writeln (output,mdl ) ;
// вывод номеров расположения матрешек на полке
for i :=n_mdl to n_mdl+mdl-1 do
write (output, mass [ i , 2 ] , ' ' ) ;
writeln ;
close ( input ) ; close ( output ) ;
end.
Задача 2. Бой с драконом.
Тип: циклические алгоритмы
Сложность: легкая
В шахматном королевстве завелся N-головый шахматный дракон, который нападал на другие фигуры и съедал их. Тогда шахматный король дал шахматному ферзю шахматный щит и шахматный меч и приказал уничтожить такую странную агрессивную фигуру. Оседлал шахматный ферзь своего шахматного коня и поскакал к логову дракона. И вот сошлись ферзь и дракон в шахматном бою, который происходит следующим образом. Сначала атакует ферзь - он может отрубить одним ударом своего шахматного меча любые головы дракона, но не более чем M за раз. Потом атакует дракон своим огненным дыханием, ферзь скрывается за шахматным щитом, а за это время у дракона вырастают K новых голов. После этого снова атакует ферзь и так далее. Бой продолжается до тех пор, пока у дракона не останется ни одной головы. В этом случае дракон погибает, а ферзь возвращается к своему королю с победой. Но бой может и не закончиться никогда. Составьте алгоритм, определяющий, сможет ферзь одолеть дракона, и если да, то какое минимальное число ударов ему нужно для этого.
Входные данные: В первой строке входного файла input.dat записаны три значения N (1 ≤ N ≤ 1000000000), M (1 ≤ M ≤ 100000), K (1 ≤ K ≤ 100000).
Выходные данные. В первую строку выходного файла output.dat необходимо вывести слово yes – если возможно преодолеть шахматного дракона и слово no – если преодолеть дракона нельзя, а вторая строчка должна содержать количество ударов для победы (если победа возможна).
Ограничение по времени: 0,5 секунды на тест.
Пример входных и выходных данных
input.dat |
output.dat |
5 2 3 |
no |
100 10 9 |
yes 91 |
Анализ:
Можно построить обычный циклических алгоритм, в котором за каждую итерации учитывать количество срубленных и регенерированных голов N = N - M + K, до тех пор, пока это возможно, то есть пока N> M.
Замечание. Надо заметить, что этот способ при очень большом значении N и малых значениях M и K (M> K) будет занимать значительное время, поскольку постепенно уменьшаем количество голов и подсчитываем удары, а не сразу ищем соответствующее значение используя операцию деления. Поэтому можно использовать другой, более легкий способ, который представлен в таблице:
Если |
Соответствующие действие |
|
M≥ N |
минимальное количество ударов, которые нанесет ферзь C = 1 |
|
иначе (M < N) |
M > K |
При любом начальном количестве голов, при каждом ударе, количество голов дракона будет уменьшаться. Сразу учтем и удар, который можно сделать в полную силу, и при котором регенерации голов уже не состоится, то есть ферзю необходимо будет на предыдущих ударах срубить N = N - M голов. Минимальное количество ударов для этого C = N div (M - K), но надо помнить, если N mod (M - K)> 0 тогда ферзю придется сделать еще один "контрольный" удар, после которого дракону уже не выжить. |
иначе (M ≤ K) |
Очевидно, что ферзь не сможет преодолеть дракона с такой бешеной скоростью регенерации голов. В таком случае ответ охарактеризуем числом C = 1. |
|
Для этого способа код будет выглядеть следующим образом:
var m, n , k , c : longint ;
output, input: text;
begin
//организация связи с файлами открытие файов на запись и чтение
assign ( input, 'input.dat' );
assign ( output, 'output.dat' ) ;
reset ( input ) ; rewrite ( output ) ;
// чтение данных из файла
read (input, n ,m, k ) ;
// задание начальных условий
c :=0;
// составление вложенных условий согласно таблицы
if m>=n
then c:=1
else if m>k
then begin
n:=n-m;
c:=n div (m-k)+1;
// учет контрольного удара
if n mod (m-k) >0 then
c:=c+1;
end
else c:=-1;
// анализ результатов и вывод в файл результата
if c=-1 then
writeln ( output, 'no' )
else begin
writeln ( output, 'yes') ;
writeln ( output, c) ;
end;
close ( input ) ; close ( output ) ;
end.
Первый способ решения (не проходит по времени на граничных условиях) :
var m, n , k , c : longint ;
output, input: text;
begin
//организация связи с файлами открытие файов на запись и чтение
assign ( input, 'input.dat' );
assign ( output, 'output.dat' ) ;
reset ( input ) ; rewrite ( output ) ;
// чтение данных из файла
read (input, n ,m, k ) ; c :=0;
if m>=n
then c:=1
else if m>k
then begin
// организация цикла для подсчета количества ударов
while n>m do begin
n:=n-m+k ;
c:=c+1;
end;
if n>0 then c:=c+1;
end
else c:=-1;
//анализ результатов и вывод в файл результата
if c=-1 then
writeln ( output, 'no' )
else begin
writeln ( output, 'yes') ;
writeln ( output, c) ;
end;
close ( input ) ; close ( output ) ;
end.
Задача 3. Персики.
Тип: работа с длинными числами
Сложность:
Продавец персиков, чтобы привлечь внимание покупателей, составила из них пирамидку: сначала выложила квадрат размера K (K рядов по K персиков в каждом), образовав таким образом самый нижний слой. Следующий слой вышел, когда между каждыми четырьмя соседними персиками нижнего слоя сверху было положено еще по персику. Так же выкладывались все последующие слои до самого верхнего, который содержал всего один персик.
Задание. Напишите программу, которая определяет количество персиков, содержащихся в этой пирамидке.
Входные данные. В единственной строке записано одно число K (1 ≤ K ≤100000000) – сторона основания пирамиды.
Выходные данные. Выведите одно целое число - количество персиков в пирамиде.
Ограничение по времени: 1 сек. на тест
Пример входных и выходных данных ввода вывода.
input.dat |
output.dat |
3 |
14 |
Анализ.
Очевидно, что для построения первого
слоя пирамиды из персиков нужно ровно
n2 фруктов, для второго слоя –
(n-1)2, третьего (n-2)2 и так далее
и лишь один персик нужен для создания
последнего верхнего слоя. Т.е., для
построения всей пирамиды необходимо
n2 + (n-1)2 +. . . +32 + 22
+ 1 персиков. Известно, что эта сумма
равна
n (n + 1) (2n + 1)/6, то есть решение задачи
сводится к нахождению этого произведения.
Так как по условию 1 ≤ N ≤ 100 000 000, то в самом крайнем случае по формуле получим: 100000000 · 100000001 · 200000001/6 = 3 333 333 383 333 333 500 000 000.
Это число превышает даже число 9 223 372 036 854 775 807 (верхний предел типа int64), поэтому при решении данной задачи необходимо испольваты так называемую «длинную арифметику». В нашем случае надо найти произведение длинных чисел (процедура mult).
Чтобы свести количество операций к минимуму, избавимся от операции деления, которая присутствует в формуле, а именно деление на 6. Понятно, что в произведении двух чисел n*(n + 1) одно из этих чисел обязательно делится на 2, соответственно и само произведение также делится на 2. Итак, осталось определить делится ли на 3 это произведение. Если это так, то произведение n (n + 1) можно разделить без остатка на 6, в другом случае 3 является делителем числа 2n + 1. Рассмотрев два варианта отдельно мы избавляемся от операции деления в общей формуле n (n + 1) (2n + 1)/6 следующим образом:
if n∗(n+1) mod 3=0
then mult (n∗(n+1) div 6 ,2∗n+1)
else mult (n∗(n+1) div 2 ,(2∗n+1) div 3);
Const NMax = 250;
Type Digit = 0..9;// объявление пользовательского типа для длинного числа
Dl_Ch = Array[1..nmax] Of Digit; // длинное число будет содеражаться в массиве
var n,n1,n2 : int64 ;
rez:real; S,st1 : String;
R,K,L : Dl_Ch;
cod:integer;
output, input: text;
//процедура обнуления массива
Procedure Zero(Var A : Dl_Ch);
Var I : Integer;
Begin
For I := 1 To NMax Do A[I] := 0;
End;
// процедура перевода строки в массив
Procedure Translate(S : String; Var A : Dl_Ch);
Var I : Word;
Begin
Zero(A); I := Length(S);
While (I >= 1) Do
Begin
If S[I] In ['0'..'9']
Then A[Length(S)- I + 1]:= Ord(S[I]) - 48;
I := I - 1
End
End;
// функция определения длины чисел
Function Dlina(C : Dl_Ch) : Integer;
Var I : Integer;
Begin
I := NMax;
While (I > 1) And (C[I] = 0) Do I := I - 1;
Dlina := I
End;
// процедура умножения двух длинных чисел
Procedure mult(A, B : Dl_Ch; Var C : Dl_Ch);
Var I, J : Integer; P : Digit; Rez : 0..99;
Begin
Zero(C);
For I := 1 To Dlina(A) Do { Цикл по количеству цифр в первом числе}
Begin
P := 0; { } Первоначально перенос равен нулю
For J := 1 To Dlina(B) Do { Цикл по количеству цифр во втором числе}
Begin
Rez := A[I] * B[J] + P + C[I + J - 1];
C[I + J - 1] := Rez Mod 10; { Очередное значение цифры в разряде I + J - 1}
P := Rez Div 10 { Перенос в следующий разряд}
End;
C[I + J] := P { последний перенос может быть отличен от нуля, запишем его в пока ещё свободный разряд}
End
End;
// процедура вывода в файл длинного числа
Procedure Print(A : Dl_Ch; ss:text);
Var I : Integer;
Begin
For I := Dlina(A) DownTo 1 Do Write(ss,A[I] : 1);
WriteLn
End;
begin
//организация связи с файлами открытие файов на запись и чтение
assign ( input, 'input.dat' );
assign ( output, 'output.dat' ) ;
reset ( input ) ; rewrite ( output ) ;
read (input, n);
n1:=n+1;
n2:=2*n+1;
//проверка условия кратности 3
if n*n1 mod 3=0
then begin // происходит преобразование числа в строку
str(((n*n1) div 6),st1);
str(n2,s);
end
else
begin // происходит преобразование числа в строку
str(((n*n1) div 2),st1);
str(n2 div 3,s);
end;
//преобразование к длинному числу
Translate(st1,K);
Translate(s,L);
//усножение чисел
mult (k, l, r);
//вывод в файл
Print(r, output);
close ( input ) ; close ( output ) ;
end.
Задача 4. Праздник.
Тип: геометрия
Сложность: средняя
В школах Дримлянди есть интересный праздник. В первый день зимы девушки выпекают пряники, печенье и другие "вкусняшки", а потом угощают ими своих одноклассников. Выпечка, приготовленная в этот день, как правило, имеет форму треугольников или прямоугольников. София приготовила на этот праздник N пряников разной формы и размера и подготовила соответствующее количество одинаковых круглых коробок, чтобы упаковать по одному прянику в коробку. Но София не учла, что некоторые пряники не помещаются в подготовленные коробки. Помогите Софии определить, какие пряники поместятся в коробки, а какие нет.
Входные данные. В первой строке записан диаметр упаковочной коробки, а во второй – количество приготовленных Софией пряников N (1 ≤ N ≤ 100). Каждая из последующих N строк содержит описание одного пряника. Если пряник имеет форму треугольника, то в начале строки записывается число 1, а затем – длины сторон этого треугольника (треугольник невырожденный).
Для прямоугольного пряника в начале строки записано число 2, а затем длины смежных сторон прямоугольника. Числа разделены одним пробелом. Все размеры – целые положительные числа, не превышающие 1017.
Выходные данные: Выведите строку с N символами. Каждый символ строки соответствует одному прянику (в порядке ввода данных). Символ "Y" означает, что пряник можно поместить в коробку, а символ "N" - что пряник поместить нельзя.
input.dat |
output.dat |
20 2 2 15 17 2 19 5 |
NY |
20 4 1 20 12 16 1 10 10 10 1 20 20 20 2 13 15 |
YYNY |
Анализ.
Случай
первый – прямоугольник. Пряник можно
поместить в коробку, если его диагональ
не превышает диаметр коробки. По известным
сторонами прямоугольника a и b найти его
диагональ можно с помощью теоремы
Пифагора: с =
Хорошая
формула и простая, но при значениях
аргументов превышающих 109 она не
предоставляет требуемой точности
вычисления. Лучше вычислить диагональ
по формуле
.
С обратных тригонометрических функций
язык Паскаль имеет только arctg, поэтому
.
Случай второй – треугольник
1. Если треугольник тупоугольный или прямоугольный, то случай, похож на случай с прямоугольником: достаточно чтобы наибольшая сторона была не более диаметра коробки. Итак, сначала определяем наибольшую сторону и сравниваем ее с диаметром коробки.
2. Если треугольник остроугольный, то ищем диаметр описанной окружности. Это лучше сделать по теореме синусов, а угол – с помощью теоремы косинусов:
var
n, i, t: integer; d1, d, cosc, x, y, z: extended;
a, b, c: int64;
begin
read (d, n);
for i:= 1 to n do
begin
read (t, a, b); { читаем тип фигуры и первые две стороны}
if t = 1 then { случай треугольника}
begin
read (c); { читаем третью сторону и находим наибольшее}
if (a>= b) and (a>= c) then begin x := a;
y := b; z := c; end;
if (b>= a) and (b>= c) then begin
x := b; y := a; z := c; end;
if (c>= b) and (c>= a) then begin
x := c; y := b; z := a; end;
if x * x>= y * y + z * z then begin {проверяем тип треугольника}
if x <= d then write ( 'Y') else
write ( 'N'); end
else begin
cosc := a / 2 / b-c / 2 / a * c / b + b / 2 / a;
d1 := c / sqrt (1-cosc * cosc);
if d1 <= d then write ( 'Y')
else write ( 'N');
end;
end
else begin { случай четырехугольника}
d1 := a / sin (arctan (a / b));
if d1 <= d then write ( 'Y') else write ( 'N');
end;
end;
end.
