понеділок, 31 жовтня 2011 р.

3. Циклические алгоритмы


Сложно представить серьезную программу без циклов. Мы полагаем, что вы уже знакомы с циклами. В этом разделе будет рассмотрен ряд задач, для решения которых необходимо использовать циклы.
Напомним, что существуют три вида циклов:
  1. Оператор цикла с параметром
for i=1..n{
  Операторы; 
}
  1. Оператор цикла с предусловием
while(Условие){
  Операторы; 
}
  1. Оператор цикла с постусловием
do{
  Операторы; 
}while(Условие);
Список задач
Задача 1: Монетки (Время: 1 сек. Память: 16 Мб Сложность: 8%)
На столе лежат n монеток. Некоторые из них лежат вверх решкой, а некоторые – гербом. Определите минимальное число монеток, которые нужно перевернуть, чтобы все монетки были повернуты вверх одной и той же стороной.

Входные данные. В первой строке входного файла INPUT.TXT записано натуральное число N (1 <= N <= 100) – число монеток. В каждой из последующих N строк содержится одно целое число – 1 если монетка лежит решкой вверх и 0 если вверх гербом.
Выходные данные. В выходной файл OUTPUT.TXT выведите минимальное количество монет, которые нужно перевернуть.
Пример
INPUT.TXT
OUTPUT.TXT
1
5
1
0
1
1
0
2
Задача 2: Арбузы (Время: 1 сек. Память: 16 Мб Сложность: 14%)
Иван Васильевич пришел на рынок и решил купить два арбуза: один для себя, а другой для тещи. Понятно, что для себя нужно выбрать арбуз потяжелей, а для тещи полегче. Но вот незадача: арбузов слишком много и он не знает как же выбрать самый легкий и самый тяжелый арбуз? Помогите ему!
Входные данные. В первой строке входного файла INPUT.TXT задано одно число N – количество арбузов. Вторая строка содержит N чисел, записанных через пробел. Здесь каждое число – это масса соответствующего арбуза. Все числа натуральные и не превышают 30000.
Выходные данные
В выходной файл OUTPUT.TXT нужно вывести два числа через пробел: массу арбуза, который Иван Васильевич купит теще и массу арбуза, который он купит себе.
Пример
INPUT.TXT
OUTPUT.TXT
1
5
5 1 6 5 9
1 9
Задача 3: Нули (Время: 1 сек. Память: 16 Мб Сложность: 16%)
Требуется найти самую длинную непрерывную цепочку нулей в последовательности нулей и единиц.
Входные данные. В единственной строке входного файла INPUT.TXT записана последовательность нулей и единиц (без пробелов). Суммарное количество цифр не превышает 100.
Выходные данные. В единственную строку выходного файла OUTPUT.TXT нужно вывести искомую длину цепочки нулей.
Пример
INPUT.TXT
OUTPUT.TXT
1
00101110000110
4
Задача 4: Загадка (Время: 1 сек. Память: 16 Мб Сложность: 18%)
Петя и Катя – брат и сестра. Петя – студент, а Катя – школьница. Петя помогает Кате по математике. Он задумывает два натуральных числа X и Y (X,Y≤1000), а Катя должна их отгадать. Для этого Петя делает две подсказки. Он называет сумму этих чисел S и их произведение P. Помогите Кате отгадать задуманные Петей числа.
Входные данные. Входной файл INPUT.TXT содержит два натуральных числа S и P, разделенных пробелом.
Выходные данные. В выходной файл OUTPUT.TXT выведите два числа Х и Y, загаданные Петей. Числа следует вывести в порядке неубывания своих значений, разделенные пробелом.
Примеры
INPUT.TXT
OUTPUT.TXT
1
4 4
2 2
2
5 6
2 3
Задача 5: Сумма (Время: 1 сек. Память: 16 Мб Сложность: 19%)
Требуется посчитать сумму целых чисел от 1 до N.
Входные данные. В единственной строке входного файла INPUT.TXT записано единственное целое число N, не превышающее по абсолютной величине 104.
Выходные данные. Вединственную строку выходного файла OUTPUT.TXT нужно вывести одно целое число — сумму чисел от 1 до N.
Пример
INPUT.TXT
OUTPUT.TXT
1
5
15

2. Разветвляющиеся алгоритмы


Мы полагаем, что Вы уже сталкивались с условным оператором и понимаете как он работает. Хотелось бы, чтобы в в этом разделе Вы закрепили свои знания на примере решения простых олимпиадных задач с использованием условий.
Напомним так же, что в языке Си наряду с условным оператором существуют так же операторы switch и "?", а в языке Pascal - оператор case. Например, в языке Си при нахождении максимального элемента из двух чисел вместо следующего условного оператора:
if(a > b) max=a; else max=b;
можно использовать следующий вариант записи:
max=(a>b)?a:b;

Список задач

Задача 1: Зарплата (Время: 1 сек. Память: 16 Мб Сложность: 4%)
В отделе работают 3 сотрудника, которые получают заработную плату в гривнах. Требуется определить: на сколько зарплата самого высокооплачиваемого из них отличается от самого низкооплачиваемого.
Входные данные. В единственной строке входного файла INPUT.TXT записаны размеры зарплат всех сотрудников через пробел. Каждая заработная плата – это натуральное число, не превышающее 105.
Выходные данные. В выходной файл OUTPUT.TXT необходимо вывести одно целое число — разницу между максимальной и минимальной зарплатой.
Примеры
INPUT.TXT
OUTPUT.TXT
1
100 500 1000
900
2
36 11 20
25
 Просьба - не решайте "в лоб"
Задача 2: Арифметика (Время: 1 сек. Память: 16 Мб Сложность: 5%)
В прошлом году Вася пошел в школу и научился считать. В этом году он изучил таблицу умножения и теперь умеет перемножать любые числа от 1 до 10 без ошибок. Друг Петя рассказал ему про системы счисления, отличные от десятичной. В частности, про двоичную, восьмеричную и даже шестнадцатеричную. Теперь Вася без труда (но уже с помощью листка и ручки) может перемножать числа от 1 до 10 и в этих системах, используя перевод из нестандартной системы в десятичную и обратно из десятичной. Например, если Васе нужно перемножить числа 101 и 1001 в двоичной системе, то он сначала эти числа переводит в десятичное представление следующим образом:
(101)2=1*22+0*21+1*20=4+0+1=5
(1001)2=1*23+0*22+0*21+1*20=8+0+0+1=9
После чего перемножение чисел 5 и 9 Вася с легкостью производит в десятичной системе счисления в уме и получает число 45. Далее производится перевод из десятичной системы счисления в двоичную. Для этого Вася делит число 45 на 2 (порядок системы счисления), запоминая остатки от деления, до тех пор пока в результате не останется число 0:

Ответ составляется из полученных остатков от деления путем их записи в обратном порядке. Таким образом Вася получает результат: (101)2 * (1001)2 = (101101)2. Но теперь Вася изучает таблицу умножения чисел от 1 до 100 в десятичной системе счисления, а поскольку запомнить такую таблицу очень сложно, то Васе придется очень долго ее зубрить. Составьте для Васи программу, которая поможет ему проверять свои знания.
Входные данные. Во входном файле INPUT.TXT записаны три натуральных числа A, B и C через пробел. Числа A и B <= 102, а C <= 106.
Выходные данные. В выходной файл нужно вывести YES в том случае, если A*B=C и вывести NO в противном случае.
Примеры
INPUT.TXT
OUTPUT.TXT
1
8 54 432
YES
2
16 19 777
NO

Задача 3: Счастливый билет (Время: 1 сек. Память: 16 Мб Сложность: 12%)
Вы пользуетесь общественным транспортом? Вероятно, вы расплачивались за проезд и получали билет с номером. Счастливым билетом называют такой билет с шестизначным номером, где сумма первых трех цифр равна сумме последних трех. Т.е. билет с номером 385916 – счастливый, т.к. 3+8+5=9+1+6. Вам требуется написать программу, которая проверяет счастливость билета.
Входные данные. В единственной строке входного файла INPUT.TXT записано одно целое число N (0 ≤ N < 106).
Выходные данные.В выходной файл OUTPUT.TXT нужно вывести «YES», если билет с номером N счастливый и «NO» в противном случае.
Примеры
INPUT.TXT
OUTPUT.TXT
1
385916
YES
2
123456
NO
 Читайте условие и думайте! (а нужно ли условие :))
Задача 4: Две окружности (Время: 1 сек. Память: 16 Мб Сложность: 17%)
На плоскости даны две окружности. Требуется проверить, пересекаются ли они.
Входные данные. Входной файл INPUT.TXT состоит из двух строк. На каждой строке записана информация об одной окружности – координаты ее центра x и y (целые числа, по модулю не превосходящие 5000) и радиус (целое число 1 ≤ r ≤ 1000).
Выходные данные. В выходной файл OUTPUT.TXT выведите «YES», если окружности пересекаются, и «NO» в противном случае.
Примеры
INPUT.TXT
OUTPUT.TXT
1
0 0 2
0 3 2
YES
2
1 1 1
4 4 1
NO
Тут конечно, и математику знать надо ;)

1. Введение


В отличии от обычных программ, создаваемых программистами повседневно, класс олимпиадных задач достаточно узок, но практичен с точки критериев выявления способности участников программировать за короткий срок. Как правило, олимпиадная задача представляет собой некоторую проблему, для решения которой требуется использовать свой IQ почти на пределе, однако, сам текст программы может быть совсем незначительным и помещаться на одной странице.
Если человек не занимался программированием, то предположительно можно оценить его способности к этой области в случае ее изучения. Многие полагают, что способности программировать связаны с умением решать математические и комбинаторные задачи. Другими словами, если у Вас в школе твердая пятерка по алгебре, геометрии и иным математическим дисциплинам, а так же умеете хорошо играть в шашки и шахматы, то вполне вероятно, что будете неплохо программировать, если начнете этим заниматься. И наоборот, если в школе у Вас тройка по алгебре, как бы вы не старались, то вряд ли программирование - это то, чем Вам стоит заниматься. Так же следует отметить, что Ваши заслуги в области освоения гуманитарных предметов мало Вам помогут в освоении программирования, которое, как Вы уже поняли, относится к точным наукам.
Приведем условную классификацию олимпиадных задач:
  • Арифметика - математические задачи, работа с большими числами (длинная арифметика), такие задачи, как правило, требуют знания формул, умение их применять, а код программ может быть небольшим
  • Геометрия - геометрические задачи, здесь может быть описана какая либо ситуация взаимодействия тел на плоскости и в пространстве
  • Динамическое программирование - задачи, направленные на выявление рекуррентных соотношений
  • Сортировка и последовательности - работа с данными, представленными в виде массива
  • Графы - задачи с графами (структурами данных, основаных на вершинах и ребрах)
  • Рекурсия - задачи на поиск с рекурсивным перебором вариантов
Конечно же, задачи могут сочетать в себе сразу несколько направлений, и часто бывает сложно конкретную задачу отнести к тому или иному разделу.
Любая олимпиадная задача подразумевает входные и выходные данные. Т.е. в формулировке задания обязательным образом описан формат входных и выходных данных, а Ваша программа должна считать эти данные, обработать и вывести результат в установленном формате. Чаще всего чтение происходит из некоторого файла INPUT.TXT, а вывод в некоторый файл OUTPUT.TXT . Т.е. для решения олимпиадных задач нужно уметь работать с файлами: читать, создавать и писать в них, а вот знания графических функций вряд ли Вам пригодятся. Стоит заметить, что многие системы, например http://acm.timus.ru, используют консольный режим ввода-вывода и работа с файлами в них не приветствуется. Помимо условия задачи, правил ввода и вывода информации на каждую задачу накладываются ограничения на время выполнения и используемую Вашей программой оперативную память.
При решении олимпиадных задач необходимо уметь работать с текстовыми файлами, т.к. от участника олимпиады, как правило, требуется написать программу, которая считывает некоторые данные из одного файла, производит определенные вычисления, а результат выводит в другой файл.
Для работы с файлами как в языке Паскаль, так и в языке Си можно обойтись без использования файловых переменных. Добавив две строчки кода в программу, можно перенаправить ввод данных с консоли на ввод из файла, а вывод на экран заменить на вывод в файл. Следующие фрагменты кода реализуют данную возможность:
  // Язык Си
  freopen("input.txt","r",stdin);
  freopen("output.txt","w",stdout);
  {Язык Паскаль}
  assign(input, 'input.txt'); reset(input);
  assign(output, 'output.txt'); rewrite(output);
В этой теме мы предлагаем решить простейшие задачи, которые помогут ознакомиться с вводом-выводом данных. Подобные задачи обычно используются на пробных турах олимпиад по программированию.
Задача 1: Неглухой телефон (Время: 1 сек. Память: 16 Мб Сложность: 1%)
Возможно, что Вы когда то играли в игру «Глухой телефон», либо слышали о ней. В этой игре участникам приходится передавать информацию друг другу различными способами: словесно, образно, бывает даже приходится писать левой рукой текст, который другой участник команды должен будет прочитать. Так же известно, что практически никогда передаваемая информация не доходит до конечного адресата. Обозначим за Fi(x) функцию, которая преобразует текст передаваемой информации x в ту, которую получит участник i+1 от участника i. Тогда последний n-й участник получит данные y, которые будут выражаться следующей формулой:
y = Fn-1(Fn-2(…F2(F1(x))))
Но Вам необходимо исключить какие-либо внешние факторы, которые могут исказить исходную информацию и Вы должны реализовать программу «неглухой телефон», которая сможет безошибочно доставлять исходные данные, т.е. в нашем случае функция Fi(x) = x для всех i от 1 до n-1.
Входные данные. В единственной строке входного файла INPUT.TXT записано натуральное число от 1 до 100.
Выходные данные. В выходной файл OUTPUT.TXT нужно вывести в точности то же число, которое задано во входном файле.
Пример
INPUT.TXT
OUTPUT.TXT
1
5
5

Задача 2: Два бандита (Время: 1 сек. Память: 16 Мб Сложность: 4%)
Бандиты Гарри и Ларри отдыхали на природе. Решив пострелять, они выставили на бревно несколько банок из-под пива (не больше 10). Гарри начал простреливать банки по порядку, начиная с самой левой, Ларри — с самой правой. В какой-то момент получилось так, что они одновременно прострелили одну и ту же последнюю банку.
Гарри возмутился и сказал, что Ларри должен ему кучу денег за то, что тот лишил его удовольствия прострелить несколько банок. В ответ Ларри сказал, что Гарри должен ему еще больше денег по тем же причинам. Они стали спорить, кто кому сколько должен, но никто из них не помнил сколько банок было в начале, а искать простреленные банки по всей округе было неохота. Каждый из них помнили только, сколько банок прострелил он сам.
Определите по этим данным, сколько банок не прострелил Гарри и сколько банок не прострелил Ларри.
Входные данные. В единственной строке входного файла INPUT.TXT записано 2 числа — количество банок, простреленных Гарри и Ларри соответственно.
Выходные данные. В файл OUTPUT.TXT выведите 2 числа — количество банок, не простреленных Гарри и Ларри соответственно.
Пример
INPUT.TXT
OUTPUT.TXT
1
4 7
6 3

Задача 3: Журавлики  (Время: 1 сек. Память: 16 Мб Сложность: 7%)
Петя, Катя и Сережа делают из бумаги журавликов. Вместе они сделали S журавликов. Сколько журавликов сделал каждый ребенок, если известно, что Петя и Сережа сделали одинаковое количество журавликов, а Катя сделала в два раза больше журавликов, чем Петя и Сережа вместе?
Входные данные. В единственной строке входного файла INPUT.TXT записано одно натуральное число S – общее количество сделанных журавликов (S < 106).
Выходные данные. В единственную строку выходного файла OUTPUT.TXT нужно вывести три числа, разделенных пробелами – количество журавликов, которые сделал каждый ребенок (Петя, Катя и Сережа).
Примеры
INPUT.TXT
OUTPUT.TXT
1
6
1 4 1
2
24
4 16 4
3
60
10 40 10

Задача 4: Игра  (Время: 1 сек. Память: 16 Мб Сложность: 4%)
В свободное время одноклассники Вася и Петя любят играть в различные логические игры: морской бой, крестики-нолики, шахматы, шашки и многое другое. Ребята уже испробовали и поиграли во всевозможные классические игры подобного рода, включая компьютерные. Однажды им захотелось сыграть во что-нибудь новое, но ничего подходящего найти не удалось.
Тогда Петя придумал следующую игру «Угадайка»: Играют двое участников. Первый загадывает любое трехзначное число, такое что первая и последняя цифры отличаются друг от друга более чем на единицу. Далее загадавший число игрок переворачивает загаданное число, меняя первую и последнюю цифры местами, таким образом получая еще одно число. Затем из максимального из полученных двух чисел вычитается минимальное. Задача второго игрока – угадать по первой цифре полученного в результате вычитания числа само это число. Например, если Вася загадал число 487, то перестановкой первой и последней цифры он получит число 784. После чего ему придется вычесть из 784 число 487, в результате чего получится число 297, которое и должен отгадать Петя по указанной первой цифре «2», взятой из этого числа. Петя успевает лучше Васи по математике, поэтому практически всегда выигрывает в играх такого типа. Но в данном случае Петя схитрил и специально придумал такую игру, в которой он не проиграет Васе в любом случае.
Дело в том, что придуманная Петей игра имеет выигрышную стратегию, которая заключается в следующем: искомое число всегда является трехзначным и вторая его цифра всегда равна девяти, а для получения значения последней достаточно отнять от девяти первую, т.е. в рассмотренном выше случае последняя цифра равна 9-2=7. Помогите Пете еще упростить процесс отгадывания числа по заданной его первой цифре, написав соответствующую программу.
Входные данные. В единственной строке входного файла INPUT.TXT задана единственная цифра К, соответствующая первой цифре полученного Васей в результате вычитания наименьшего загаданного Васей значения из наибольшего.
Выходные данные. В выходной файл OUTPUT.TXT нужно вывести значение полученной Васей разности.
Примеры
INPUT.TXT
OUTPUT.TXT
1
5
594
2
2
297
3
7
792

Начинаем подготовку к олимпиадам


КУРС ОЛИМПИАДНИКА
Этот курс я беззастенчиво слямзил  скопировал из http://www.acmu.ru/
Данный раздел содержит набор тем для самостоятельного изучения основ курса олимпиадного программирования. Каждая тема включает теоритическую часть и набор задач, сложность которых растет от темы к теме. Для многих рассматриваемых задач приведен словесный разбор их решений. Но все же мы рекомендуем Вам сначала попытаться их решить самостоятельно, и лишь в том случае, когда это сделать не получается, прибегать к просмотру их решения.
Этот курс предназначен для школьников, имеющих некоторые знания в области программирования на уровне понимания синтаксиса языка и простейших алгоритмов.
Список тем (темы сокращенно и переработано буду добавлять в следующих постах)