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

Задача 3. "Функция"

  1. Условие задачи.

Функция F(n) для целых неотрицательных n определена так: F(0)=0, F(1)=1, F(2n) = F(n), F(2n+1)=F(n)+F(n+1).

Для данного N найти и напечатать F(n). Обязательное условие: N

столь велико, что недопустимо заводить массив из N чисел.

  1. Алгоритм решения.

Основная идея алгоритма заключается в том, что при разложении f(2n+1) на f(n) и f(n+1) мы должны вычислить 2 значения функции. Либо n, либо n+1 окажется нечетным и для его вычисления понадобится опять вычислять 2 значения функции. А для четного аргумента еще одно. На первый взгляд, кажется, что теперь нам надо вычислить значения F для 3 аргументов, но на самом деле 2 из них (аргументов) всегда совпадут! То есть кол-во вычислений функции на каждом шаге не увеличивается.

Пример:

F(26) = F(13) = F(6)+F(7) = F(3)+F(3)+F(4) = 2F(3)+F(4) =

=2(F(1)+F(2))+F(2) = 2F(1)+3F(2) = 5F(1) = 5

  1. Программная реализация

Program func; var

c, {Текущий четный аргумент}

nc, {Текущий нечетный аргумнт}

kc, {Коэффициент при четном аргументе}

knc, {Коэффициент при нечетном аргументе} n:LongInt;

{В переменной c всегда должен быть четный аргумент, а в nc - нечетный. Эта процедура меняет местами значения переменных c и nc, если это необходимо}

Procedure Correct; var Temp:LongInt;

Begin

if odd(c) then Begin Temp:=c; c:=nc; nc:=Temp; Temp:=kc; kc:=knc;

knc:=Temp; End;

End;

Begin

Write('Введите число '); ReadLn(N);

n:=abs(n); {Вычислим модуль n} if n=0 then Writeln('0') else

Begin

while n mod 2 = 0 do n:=n div 2; {уменьшаем n до нечетного числа}

c:=n div 2; {Разложим n на четное}

nc:=n-c; {и нечетное числа} if c=0 then kc:=0 else kc:=1;

knc:=1;

while (c>2) or (nc>2) do Begin

Correct; {поменяем c и nc, если нужно}

c:=c div 2; {получим новый аргумент}

kc:=kc+knc; {получим коэфф. при нем}

nc:=nc-c; {вычислим второй аргумент} End;

WriteLn(Kc+knc); {Выведем результат} ReadLn; {Подождем}

End; End.

Задача 4 „REBUS.

Составить программу REBUS, которая определяет все 4-значные числа на интервале [M, N], удовлетворяющие условиям: a) abcd - 4-цифровое число; b) a, b, c, d - разные цифры; c) ad - cd = a + b + c + d; и подсчитывает общее количество этих чисел. Во входном файле REBUS.DAT в 1-м и 2-й строчках находятся два числа M и N. В файле REBUS.SOL выводятся числа, удовлетворяющие условиям а)-с), и их количество.

файл REBUS.DAT

файл REBUS.SOL

5128 5467

5139 5302 2

program REBUS; var a,b,c,d,m,n,k,x,i:integer; f,f1,f2:text; begin assign (f,'rebus.dat'); readln(m,n); rewrite(f); writeln(f,m); writeln(f,n); close(f); for i:=m to n do begin a:=i div 1000; b:=i mod 1000 div 100; c:=i mod 100 div 10; d:=i mod 10; if (a <> b) and (a <> c) and (a <> d) and (b <> c) and (b <> d) and (c <> d) and (a*d-c*d=a+b+c+d) then begin k:=k+1; assign(f1,'rebus.sol'); append(f1); writeln(f1,i); close(f1); end; end; assign(f1,'rebus.sol'); rewrite(f1); writeln(k); writeln(f1,k); close(f1)

end.

Задача 4 „ Кубики. “.

Кубик с ребром N см покрасили и разрезали на кубики с ребром 1 см. При этом появились такие, у которых окрашено разное количество граней. Например, если N = 3, то после разрезания будет 8 кубиков, у которых окрашено три грани, 12 с двумя гранями, 6 с одной, а один кубик будет совсем неокрашенный. Составьте программу, которая бы определяла, сколько кубиков с каждой возможным количеством окрашенных граней.

Технические условия

Имя программы

CUBES.

Ввод

С клавиатуры вводится целое число N (от 1 до 1292)

Вывод

На экран или форму выводятся различные варианты окрасок и их количества в формате: количество_окрашеных_граней/количество_кубиков в порядке возрастания первого параметра

Пример

input.txt

output.txt

1

3

0/1 1/6 2/12 3/8

program cubes; uses crt; var x,x1,x2,x3,x0,y,z,k,n:integer; s:string; f,g:text; begin assign(f,'cubes.dat'); reset(f); readln(f,y); close(f) ; x3:=8; x1:=sqr(y-2)*6; x0:=(sqr(y-2))*(y-2); x2:=(y-2)*4*2+(y-2)*4; assign(g,'cubes.sol'); rewrite(g); writeln(g,'0/',x0,' 1/',x1,' 2/',x2,' 3/',x3); close(g); end.

Тема: Сортировка и поиск

Задача “Шифровка”

Мальчик Петя чрезвычайно увлекается различными шпионскими рассказами и недавно от чтения романов со стрельбой и погонями перешел к изучению серьезной литературы. Особенно его заинтересовал один из методов шифровки секретных сообщений, прочитанный им в брошюрке по криптографии из серии “Библиотечка кровавого режима”.

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

Формат входных данных

Во входном файле записано целое число N — количество чисел  (1 ≤ N ≤ 300 001). Далее записано N целых чисел Mi (1 ≤ Mi ≤ 2•109).

Формат выходных данных

В выходной файл выведите секретное число.

Ограничение

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

Алгоритм решения

Разобьем каждое двузначное число на разряд десятков и разряд единиц (однозначные числа будут иметь в качестве разряда десятков 0)

Получим две цифры

Посчитаем, сколько раз встречалось каждая цифра

Выберем то, которое встречалось некратное трем число раз, его индекс и будет ответом(один проход по массиву и подсчет остатка от деления каждого элемента на 3).

Умножим цифру десятков на 10 и прибавим к ней цифру единиц.

Решение

Program shifr;

uses crt;

var

A : array[1..10, 0..9] of longint; {объявление двухмерного массива}

  i, j, k, n: longint; f1, f2: text;

begin

assign(f1,’input.txt’); reset(f1);

assign (f2,’output.txt’);rewrite (f2);

for i := 1 to 10 do

for j := 0 to 9 do

{заполняем таблицу нулями }

A[i, j] := 0;

read(f1,n);

for i := 1 to n do begin

read(f1,k);

j := 1; {номер разряда}

while k <> 0 do begin

{на месте j добавилась цифра k mod 10}

inc(A[j, k mod 10]);

{выкидываем последнюю цифру }

k := k div 10;

{переходим к следующему разряду}

inc(j);

end;

end;

k := 0; {здесь будем восстанавливать число начиная со старших разрядов}

for i := 10 downto 1 do begin

{ переходим к следующей цифре}

k := k * 10;

{перебираем все цифры}

for j := 0 to 9 do

{нашли "секретную" цифру}

if A[i, j] mod 3 <> 0 then

{и прибавляем ее к ответу}

k := k + j;

end;

writeln(f2,k);

close (f1);

close (f2);

end.

Тестирование задачи

Input.txt

Output.txt

11 3 1 2 3 1 3 2 2 1 3 3

3

10

22 12 34 22 12 22 12 34 34 25

25

Тема: Эффективные структуры данных

Задача Роботы

Сообщество роботов живет по следующим законам: один раз в год они объединяются в полностью укомплектованные группы по 3 или 5 роботов (причем число групп из 3 роботов - максимально возможное). За год группа из 3 роботов собирает 5, а группа из 5 - 9 новых собратьев. Каждый робот живет 3 года после сборки. Известно начальное количество роботов k, все они только что собраны. Определить, сколько роботов будет через n лет.

Входные данные

В первой строке исходного файла Input.txt записано начальное число роботов, во второй строке – количество лет.

Выходные данные. В файл Output.txt выведено одно число – искомое количество роботов

Input.txt

Output.txt

13

7

10603

Алгоритм решения

Создадим массив r[3], где r[1], r[2], r[3] - количество роботов соответствующего возраста. Т

Обозначим x - количество троек, y - количество пятерок, которое можно сформировать из общего числа роботов.

Определим возможное количество троек и пятерок роботов.

Вычислим количество создаваемых роботов 5*х+9*у в год

Тогда общее количество роботов S= r[1] + r[2]+ r[3].

Programrobotu;

vark,i,n:integer;

fi,fo:text;

p:byte;

s,x,y:longint;

r:array [1..3] oflongint;

begin

assign (fi,’input.txt’); reset (fi); read (fi,n); close (fi);

assign (fo,’output.txt’); rewrite (fo);

r[1]:=k; r[2]:=0; r[3]:=0; s:=k;

{заполним массив, исходное количество роботов-первый элемент массива}

for i:=1 to n do begin

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

x:=sdiv 3; {находим возможное количество троек роботов}

p:=smod 3; {находим остаток роботов}

casepof {рассматриваем варианты создания групп по три и пять роботов}

0: y:=0; {если остаток равен нулю, будут только тройки роботов}

1: beginx:=x-3; y:=2;end; {если 1, то забираем три тройки и создаем две пятерки}

2: beginx:=x-1; y:=1;end; {если остаток 2, то забираем одну тройку и создаем одну пятерку}

end;

r[3]:=r[2]; r[2]:=r[1]; r[1]:=5*x+9*y;

{добавляем в массив число вновь созданных роботов}

{формируем массив, в котором данные обновляются каждый год}

s:=r[1]+r[2]+r[3];

{роботы, прожившие более трех лет, автоматически убираются из массива}

end;

write(fo, s);

close (fo);

end.

Тестирование задачи

Начальное число роботов

Число лет

Количество роботов

8

1

22

8

2

60

10

5

1286

10

10

143702

15

3

273

200

2

1424

1000

10

13284366

Тема: Элементы вычислительной геометрии.

Задача «Отрезок»

Условие задачи. Отрезок на плоскости задается двумя несовпадающие конечными точками A (x1; y1) и B (x2; y2). С точки С (х3; у3) к прямой, содержащей отрезок АВ, проводится перпендикуляр. Определить, попадает перпендикуляр на отрезок АВ или на его продолжение.

Во входном файле содержится три пары чисел, являющихся координатами точек А, В, С.

В выходном файле содержится ответ «На отрезок» или «На продолжение». Пример входного и выходного файлов

S.txt

S1.txt

4 4 7 3 9 5

На продолжение