f b g h ; j g : m d b n ^ j z e v g h ] h k m ^ z j [ x ...math.csu.ru › ~alexeev › arc ›...

153
МИНОБРНАУКИ РОССИИ Федеральное государственное бюджетное образовательное учреждение высшего образования «Челябинский государственный университет» Миасский филиал М. Н. Алексеев, Т. М. Алексеева ПРАКТИКУМ ПО ПРОГРАММИРОВАНИЮ НА ЯЗЫКЕ С++ Учебное пособие Миасс 2018

Upload: others

Post on 23-Jun-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

МИНОБРНАУКИ РОССИИ

Федеральное государственное бюджетное образовательное

учреждение высшего образования

«Челябинский государственный университет»

Миасский филиал

М. Н. Алексеев, Т. М. Алексеева

ПРАКТИКУМ

ПО ПРОГРАММИРОВАНИЮ

НА ЯЗЫКЕ С++

Учебное пособие

Миасс

2018

Page 2: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

2

УДК 004.432.2

ББК 32.973.26-018.1 я73

А 47

Алексеев, М. Н.

А 47 Практикум по программированию на языке С++ :

учебное пособие / М. Н. Алексеев, Т. М. Алексеева ;

ФГБОУ ВО «ЧелГУ». – Миасс : Геотур, 2018. – 152 с.

ISBN 978-5-89204-274-1

Основная цель учебного пособия – помочь освоить азы популярного

языка программирования С++. Материал рассчитан на систематическую

работу обучающихся, не имеющих значительного опыта

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

сборника заданий – ориентация на автоматическую проверку задач на

специализированных сайтах.

Учебное пособие рекомендуется для обучения основам

программирования на процедурном языке С++ студентов специальностей

«Прикладная математика и информатика», «Фундаментальная информатика

и информационные технологии» в рамках курса «Практикум на ЭВМ».

Издание может быть полезно учащимся школ, лицеев и гимназий,

желающим углублённо изучать программирование.

Рецензенты:

Кафедра «Прикладная математика и ракетодинамика» филиала ФГБОУ ВО

«ЮУрГУ» (НИУ) в г. Миассе.

Л. Б. Сенкевич, к.п.н., доцент кафедры кибернетических систем ФГБОУ ВО

«Тюменский индустриальный университет».

ББК 32.973.26-018.1 я73

© ФГБОУ ВО «ЧелГУ»,

2018

Page 3: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

3

СОДЕРЖАНИЕ

ВВЕДЕНИЕ ......................................................................................................... 5

1. ПРОСТЕЙШИЕ ПРОГРАММЫ ........................................................ 11

1.1. ЛИНЕЙНЫЕ АЛГОРИТМЫ .............................................................. 11

1.2. ВЕТВЛЕНИЯ .......................................................................................... 15

2. ЦИКЛИЧЕСКИЕ АЛГОРИТМЫ ...................................................... 22

2.1. ЦИКЛЫ С ПАРАМЕТРОМ ................................................................. 22

2.2. ЦИКЛЫ С ПРЕДУСЛОВИЕМ ........................................................... 25

2.3. ЦИКЛЫ С ПОСТУСЛОВИЕМ........................................................... 29

2.4. БИНАРНЫЙ ПОИСК ........................................................................... 34

3. ОБРАБОТКА СТРОК ........................................................................... 37

3.1. СИМВОЛЫ ............................................................................................. 37

3.2. СТРОКИ .................................................................................................. 40

3.3. СТРОКОВЫЕ ПОТОКИ ...................................................................... 45

3.4. СИСТЕМЫ СЧИСЛЕНИЯ .................................................................. 46

4. ФУНКЦИИ .............................................................................................. 49

5. ОДНОМЕРНЫЕ МАССИВЫ .............................................................. 56

5.1. ПРОСТОЙ ПРОХОД ПО МАССИВУ ............................................... 56

5.2. ПРЕОБРАЗОВАНИЯ МАССИВОВ ................................................... 60

5.3. СТРУКТУРЫ И МАССИВЫ СТРУКТУР ....................................... 63

6. СОРТИРОВКИ МАССИВОВ .............................................................. 68

6.1. КВАДРАТИЧНЫЕ СОРТИРОВКИ ................................................... 68

6.2. БЫСТРЫЕ СОРТИРОВКИ ................................................................. 72

6.3. ЛИНЕЙНЫЕ СОРТИРОВКИ ............................................................. 77

7. ДВУМЕРНЫЕ МАССИВЫ ................................................................. 81

7.1. ПРЕОБРАЗОВАНИЯ МАТРИЦ ......................................................... 81

7.2. СИМВОЛЬНЫЕ МАТРИЦЫ .............................................................. 86

7.3. ЧИСЛОВЫЕ МАТРИЦЫ .................................................................... 89

8. ФАЙЛЫ ................................................................................................... 95

8.1. ФАЙЛОВЫЙ ВВОД И ВЫВОД .......................................................... 95

Page 4: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

4

8.2. СОРТИРОВКИ ФАЙЛОВ .................................................................... 97

8.3. ОБРАБОТКА ФАЙЛОВ ..................................................................... 101

9. РЕКУРСИЯ ........................................................................................... 105

10. СТРУКТУРЫ ДАННЫХ И АЛГОРИТМЫ ИЗ СТАНДАРТНОЙ

БИБЛИОТЕКИ ШАБЛОНОВ STL .................................................. 113

10.1. СТЕКИ ................................................................................................... 113

10.2. ВЕКТОРЫ ............................................................................................. 121

10.3. СПИСКИ ................................................................................................ 124

10.4. ОЧЕРЕДИ .............................................................................................. 130

10.5. МНОЖЕСТВА ...................................................................................... 133

10.6. АССОЦИАТИВНЫЕ МАССИВЫ И ЛАМБДА-ФУНКЦИЯ ..... 139

11. ПЕРЕОПРЕДЕЛЕНИЕ ОПЕРАЦИЙ И ДЛИННАЯ

АРИФМЕТИКА .................................................................................... 142

РЕКОМЕНДУЕМАЯ ЛИТЕРАТУРА ....................................................... 149

ЭЛЕКТРОННЫЕ РЕСУРСЫ ..................................................................... 151

Page 5: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

5

Инклуд «иострим»

Юзинг нэймспэйс эстэдэ;

Мэйн скобка скобка…

Хокку С++-программиста

ВВЕДЕНИЕ

Это пособие написано на основе опыта проведения

лабораторных работ по дисциплине «Практикум на ЭВМ» в 1–2

семестрах 1 курса бакалавриата по направлениям «Прикладная

математика и информатика» и «Фундаментальная информатика и

информационные технологии» в Миасском филиале ЧелГУ.

Традиционно лабораторным работам «Практикума на ЭВМ»

предшествуют лекции по «Языкам программирования», а также по

«Информатике» («Основам программирования»). Рассмотренные

на этих лекциях темы отрабатываются на компьютерах в рамках

практикума, и соответствующие задания для выполнения на

лабораторных работах включены в это пособие. Эти курсы тесно

взаимосвязаны, поэтому важно, чтобы они изучались именно

параллельно, а не один после другого.

Главной из целей настоящего курса является освоение

процедурного программирования на языке С++ с использованием

библиотек STL. Объектно-ориентированное программирование на

С++ в рамки этого курса не входит, соответствующий курс (ООП)

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

не только на С++, но и, например, на Java или C#.

Другой важной целью является освоение студентами

основных приёмов и методов программирования, основанное на

изучении базовых алгоритмов и структур данных.

Нам представляется достаточно эффективным подход к

изучению программирования, основанный на решении

наибольшего количества небольших задач-упражнений,

иллюстрирующих и закрепляющих конкретные темы. Проверку

корректности решений этих задач можно и нужно возложить на

соответствующие системы автоматической проверки по наборам

тестов. При этом удаётся значительно повысить

Page 6: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

6

производительность труда преподавателя при контроле

результатов обучения, а также повысить мотивацию в учебной

работе студентов за счёт постановки для них конкретных

количественных ориентиров (в том числе и для балльно-

рейтинговой системы) и введения соревновательного элемента.

Задания практикума разбиты на разделы и темы. Для

некоторых задач приведены полные тексты условий и

рекомендуемые решения, иногда даже 2-3 варианта разными

способами. Остальные задачи соответствующих разделов на

сайтах упомянуты по номерам и названиям, их предлагается найти

на сайте и решить самостоятельно. К некоторым таким задачам

предложены указания по их решению. Всего в сборнике

представлены или упомянуты более 200 задач, примерно треть из

них снабжена оригинальными авторскими решениями.

Основная часть заданий взята со специальных сайтов с

автоматической проверкой правильности решения заданий на

наборах тестов. Это сайты acmp.ru [16] (автор – методист

Красноярского краевого Дворца пионеров Сергей Николаевич

Беляев) и ipc.susu.ru [17] (автор – доцент НИУ ЮУрГУ Андрей

Константинович Демидов), которые мы далее будем называть

acmp и ipc. Авторство большинства из задач на этих сайтах не

указано, известно лишь, что они взяты из материалов различных

олимпиад по программированию для школьников и студентов за

несколько десятков лет. Многие из таких задач уже

использовались в пособиях и сборниках задач по

программированию других авторов, например в книге [5]

преподавателя Вологодского госуниверситета Фёдора

Владимировича Меньшикова (с решениями на языке Pascal). В

пособиях такого рода важны не только и не столько тексты

условий задач и их оригинальность, сколько предлагаемые

авторами на примере этих задач подходы, алгоритмические,

языковые и стилевые средства их решения, а также приобретаемые

при этом студентами в дидактически обоснованной

последовательности навыки программирования. Именно этим

руководствовались авторы практикума при подборе задач. Кроме

Page 7: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

7

того, некоторые важные для закрепления материала задачи

специально придуманы авторами настоящего практикума и

предполагают ручную проверку.

Рис. 1. Регистрация на сайте acmp.

Рис. 2. Открытие доступа к своим решениям преподавателю.

Для эффективной работы в рамках практикума студентам

следует зарегистрироваться – создать учётные записи на этих

Page 8: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

8

сайтах, указав реальные сведения о себе по-русски (фамилия, имя,

город, вуз, курс, группа), и аккуратно записать и сохранить логины

и пароли к ним (см. рис. 1).

На сайте acmp после регистрации студенту следует в разделе

«Курсы» убедиться, что он включён в свою группу, после чего

необходимо нажатием на соответствующую надпись под списком

группы «Открыть» доступ к своим решениям преподавателю (см.

рис. 2).

Подобным же образом организована регистрация

пользователей на сайте ipc (см. рис. 3), но там преподаватель

получает возможность просмотра студенческих решений задач из

заданных им наборов заданий автоматически.

Рис. 3. Регистрация на сайте ipc

На сайте acmp предлагается работать в разделе «Курсы» – в

1-м семестре – в подразделе «Язык программирования С++», а во

2-м семестре – в подразделе «Решение олимпиадных задач». На

сайте ipc следует работать в разделе «Рабочее место участника»,

выбирая назначенные преподавателем наборы заданий.

Во время проведения лабораторных работ в компьютерной

аудитории преподаватель имеет возможность просматривать

экраны студентов, находить ошибки и указывать на них

студентам. Кроме того, как во время аудиторных занятий, так и в

Page 9: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

9

любое другое время преподавателю доступны тексты сданных на

сайт решений и результаты их тестирования проверяющей

системой, что позволяет их оценивать, проверять на плагиат и

обсуждать со студентами, в том числе и через средства сетевого

общения и в социальных сетях.

Уточнить особенности использования тех или иных

конструкций языка С++ и шаблонов STL можно в книгах [1, 4, 7,

8, 10–13] и на сайтах www.cplusplus.com [18] и ru.cppreference.com

[19]. Везде подразумевается использование компилятора GNU

C++ 5.1.0 и выше (по стандарту С++11 и выше). С базовыми

алгоритмами и структурами данных можно познакомиться в

книгах [2, 3, 5, 6, 9, 14, 15] и на сайтах [20–24]. Материалы к

зачётам и экзамену по дисциплине можно найти на

соответствующих страницах сайтов ЧелГУ [30, 31].

Важным вопросом является выбор среды программирования

(IDE – Interactive Development Environment). В принципе, писать

тексты программ можно в любом текстовом редакторе, например

в Блокноте или должным образом настроенном notepad+, но всё же

удобнее работать в специализированной среде. Для многих

профессионалов примерами таких IDE являются Qt или Microsoft

Visual Studio или Code::Blocks, но мы рекомендуем для начала

простую, но полноценную среду Dev-C++ [25] («дэвсипипи»),

имеющую, в частности, Portable-версию, позволяющую носить её

с собой на флэшке и запускать на любом компьютере без

инсталляции. Ещё одна простая и компактная среда,

рекомендуемая, в частности, сайтом ipc, – это MinIDE [26]. Иногда

удобно работать с web-IDE на сайтах типа cpp.sh [27] или

ideone.com [28] или jdoodle.com [29].

Следует настроить компилятор для полного использования

возможностей последних версий языка С++ (11, 14, 17…), для

чего, например, в меню IDE Dev-C++ следует найти вкладку

Сервис – Параметры компилятора – Настройки – Генерация кода

– Language standard и установить значение «GNU C++11». Здесь

же можно выбрать уровень оптимизации при компиляции и

разрядность – 32 или 64 бита (см. рис. 4).

Page 10: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

10

Рис. 4. Настройка компилятора.

Хорошим тоном и удобной привычкой является организация

на экране рядом двух неперекрывающихся окон, где в одном

окне – браузер со страницей решаемой задачи на сайте

проверяющей системы, а в другом – IDE с кодом отлаживаемой

программы (см. рис. 5).

Рис. 5. Организация рабочих окон.

Page 11: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

11

1. ПРОСТЕЙШИЕ ПРОГРАММЫ

1.1. ЛИНЕЙНЫЕ АЛГОРИТМЫ

Сайт acmp, раздел «Курсы/Язык программирования С++/

Введение»

Тема «Арифметика». Задачи A..F

Задача А. А+В (1)

Требуется сложить два целых числа А и В.

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

INPUT.TXT записано через пробел два натуральных числа, не

превышающих 109.

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

OUTPUT.TXT нужно вывести одно целое число — сумму чисел А

и В.

Пример

INPUT.TXT OUTPUT.TXT

2 3 5

На самом деле в файлах INPUT.TXT и OUTPUT.TXT

проверяющая система просто хранит свои тесты, а мы в своих

программах почти всегда можем считать, что данные вводятся с

клавиатуры и выводятся на экран.

Поэтому читаем условие следующим образом:

Входные данные. В единственной строке вводятся через пробел

два натуральных числа, не превышающих 109.

Выходные данные. В единственную строку нужно вывести одно

целое число — сумму чисел А и В.

Пример

Ввод Вывод

2 3 5

Замечаем, что речь идёт о натуральных числах, не

превышающих миллиарда, что позволяет использовать для их

хранения переменные типа int, и составляем нашу первую

программу на языке С++ в выбранной IDE (см. рис. 5):

Page 12: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

12

1 #include <iostream>

2 using namespace std;

3 main(){

4 int a,b;

5 cin>>a>>b;

6 cout<<a+b; }

Запускаем нашу программу на компиляцию и исполнение,

вводим через пробел два числа, например «2 3», и получаем

правильный результат «5».

После этого копируем текст нашей программы из окна

редактора IDE, вставляем его на сайте acmp на странице с этой

задачей в окно «Исходный код решения» и нажимаем кнопку

«Отправить». Если ошибок не было, появится ответ «Accepted»

(принято), иначе пытаемся понять, что не так, исправляем ошибки,

добиваемся приёма нашего решения системой и переходим к

следующим задачам.

Указания к решению других задач темы «Арифметика»

B 108 Неглухой

телефон

Надо просто вывести введенное число

C 903 Бисер N+1

D 195 Эния N*A*B*2

F 33 Два бандита Учесть, что если Гарри прострелил G, а

Ларри – L банок, то всего банок G+L-1

Задача Е. Следующее и предыдущее (1109)

Напишите программу, которая считывает целое число и выводит

текст с упоминанием следующего и предыдущего для него чисел.

Входные данные. Вводится целое число, не превосходящее 1000

по абсолютной величине.

Выходные данные. Выведите текст, аналогичный приведенному в

примере. При выводе следует учесть все пробелы и знаки

препинания.

Page 13: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

13

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

13 The next number for the number 13 is 14.

The previous number for the number 13 is 12.

1 #include <iostream> 2 using namespace std; 3 main(){ 4 int n; 5 cin>>n; 6 cout<<"The next number for the number "<<n

<<" is "<<n+1<<"."<<endl; 7 cout<<"The previous number for the number "

<<n<<" is "<<n-1<<"."; }

Указания к решению некоторых задач темы «Целые числа»

A 3 Пятью пять –

двадцать пять!

Квадрат числа порядка 105

выходит за пределы типа int. Надо

напечатать результат реализации

предложенного алгоритма и

допечатать «25». В случае А==5

при этом будет напечатано 025,

поэтому его рассмотреть отдельно.

B 1038 Перевязь Если добавить к длине 9 и

поделить на 10, получим

требуемое количество дециметров.

C 1110 Последняя цифра Используем операцию %10 –

остаток от деления на 10.

D 1111 Число десятков Используем операцию /10 –

результат деления на 10.

E 1112 Сумма цифр

числа

Используем операции / и %

Page 14: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

14

Решить задачи

F 1113 Проверьте делимость

G 1114 МКАД

H 1115 Делёж яблок

После этого следует решить задачи темы «Вывод формул»

A 1003 Магазин канцелярских товаров

B 773 Гулливер

C 92 Журавлики

D 1116 Разность времён

E 1117 Конец уроков

F 1118 Улитка

Page 15: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

15

1.2. ВЕТВЛЕНИЯ

Сайт acmp, «Курсы/Язык программирования С++/ Условный

оператор»

Тема «Простые сравнения». Задачи A..J

Задача А. Больше-меньше (25)

Одна из основных операций с числами – их сравнение. Мы

подозреваем, что вы в совершенстве владеете этой операцией и

можете сравнивать любые числа, в том числе и целые. В данной

задаче необходимо сравнить два целых числа.

Входные данные. В двух строчках на входе записаны числа A и B,

не превосходящие по абсолютной величине 2*109.

Выходные данные. Выведите один символ ‘<’, если A < B, ‘>’, если

A > B и ‘=’, если A=B.

Примеры

№ Ввод Вывод № Ввод Вывод № Ввод Вывод

1 5 <

7

2 -7 >

-12

3 13 =

13 1 #include <iostream>

2 using namespace std; 3 int a,b; 4 main(){

5 cin>>a>>b;

6 if(a>b)cout<<’>’;

7 else if(a<b)cout<<’<’;

8 else cout<<’=’; }

Задача C. Счастливый билет (52)

Счастливым билетом называют такой билет с шестизначным

номером, где сумма первых трех цифр равна сумме последних

трех. Т.е. билет с номером 385916 – счастливый, т.к. 3+8+5=9+1+6.

Написать программу, которая проверяет «счастливость» билета.

Page 16: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

16

Входные данные. Одно целое число N (0 ≤ N < 106).

Выходные данные. Вывести «YES», если билет с номером N

счастливый, и «NO» в противном случае.

Примеры

№ Ввод Вывод

1 385916 YES

2 123456 NO

С помощью операций деления целого на целое без остатка и

получения остатка от деления целого на целое разобьём 6-значное

число на два 3-значных, в которых выделим отдельные цифры и

подсчитаем их суммы для сравнения. 1 #include <iostream> 2 using namespace std; 3 main (){ 4 int n,a,b; 5 cin>>n; 6 a=n/1000; 7 b=n%1000; 8 a=a%10+(a/10)%10+a/100; 9 b=b%10+(b/10)%10+b/100; 10 if(a==b)cout<<"YES"; 11 else cout<<"NO"; }

Указания к решению некоторых задач темы «Простые

сравнения»

B 8 Арифметика Не пугайтесь большого текста,

фактически описание задачи

начинается со слов «Входные

данные». Не забудьте, что сравнение

на равенство выглядит так:

if(a*b==c)cout<<”YES”.

D 21 Зарплата Кроме трёх переменных А, В, С для

ввода зарплат сотрудников заведите

ещё переменные Zmax и Zmin,

найдите их значения и выведите

разницу.

Page 17: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

17

E 61 Баскетбол Кроме двух переменных a и b введите

переменные для суммирования

результатов s1 и s2, обнулите их, а

затем 4 раза прочитайте a и b и

добавьте их значения к s1 и s2

соответственно, а затем сравните их

так же, как в задаче А. Больше-

меньше.

F 324 Четырехзначный

палиндром

Подобно задаче С, используя % и /,

выделите отдельные цифры и

сравните их попарно.

G 539 Торт Для чётного числа едоков

(if(n%2==0)) нужно n/2 разрезов, для

нечётного n, но при n==1 – 0 разрезов.

H 754 Три толстяка Сначала проверить, что вес каждого

укладывается в допустимые рамки, а

затем, если нет ошибки, искать

максимум.

Задача I. Золотой песок (685)

Сотрудники завода по производству золотого песка из воздуха

решили поправить свое финансовое положение. Они пробрались

на склад завода, где хранился золотой песок трех видов. Один

килограмм золотого песка первого вида они смогли бы продать за

A1 рублей, второго вида – за A2 рублей, а третьего вида – за A3

рублей. Так получилось, что у сотрудников оказалось с собой

только три емкости: первая была рассчитана на B1 килограммов

груза, вторая на B2 килограммов, а третья на B3 килограммов. Им

надо было заполнить полностью все емкости таким образом,

чтобы получить как можно больше денег за весь песок. При

заполнении емкостей нельзя смешивать песок разных видов, то

есть в одну емкость помещать более одного вида песка, и

заполнять емкости песком так, чтобы один вид песка находился

более чем в одной емкости.

Page 18: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

18

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

сумму предприимчивые сотрудники смогут продать весь песок в

случае наилучшего для себя заполнения емкостей песком.

Входные данные. 6 натуральных чисел A1, A2, A3, B1, B2, B3,

записанные в одной строке через пробел. Все числа не превосходят

100.

Выходные данные. В единственную строку нужно вывести

единственное целое число – сумму в рублях, которую смогут

сотрудники заработать в случае наилучшего для себя заполнения

емкостей песком.

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

1 2 3 3 2 1 14

Добьёмся того, чтобы стало A1>= A2>= A3 и B1>= B2>= B3, и

просуммируем произведения соответствующих пар:

1 #include <iostream> 2 using namespace std; 3 main(){ 4 int a1,a2,a3,b1,b2,b3,c; 5 cin>>a1>>a2>>a3>>b1>>b2>>b3; 6 if(a1<a2){c=a1;a1=a2;a2=c;} 7 if(a2<a3){c=a2;a2=a3;a3=c;} 8 if(a1<a2){c=a1;a1=a2;a2=c;} 9 if(b1<b2){c=b1;b1=b2;b2=c;} 10 if(b2<b3){c=b2;b2=b3;b3=c;} 11 if(b1<b2){c=b1;b1=b2;b2=c;} 12 cout<<a1*b1+a2*b2+a3*b3; }

Кстати, конструкцию обмена значениями

{c=a1;a1=a2;a2=c;} можно заменить на вызов функции

swap(a1,a2);

Page 19: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

19

Задача J. Светофор (1006)

Рассмотрим самый обычный вертикальный автомобильный

светофор, состоящий из трех секций для индикации (сверху вниз):

красного, желтого и зеленого сигналов. Напомним его

функционал. Каждая секция может отражать два цвета:

соответствующий ей цвет во включенном состоянии и черный

цвет в выключенном состоянии. Когда светофор исправен, то ему

доступно 6 возможных состояний. В обычном рабочем режиме мы

имеем следующий алгоритм работы:

1. горит только зеленый сигнал;

2. зеленый сигнал мигает;

3. гаснет зеленый, загорается желтый;

4. гаснет желтый, загорается красный;

5. загорается желтый и горит вместе с красным;

6. гаснут желтый и красный, и все повторяется с пункта 1.

Светофор также может работать в режиме нерегулируемого

перекрестка, когда присутствует только желтый мигающий

сигнал.

По текущей индикации сигналов светофора следует определить

его следующее состояние, в которое он должен перейти, либо

определить, что светофор неисправен.

Входные данные. В трех строках вводится описание текущего

состояния светофора. Первая строка описывает верхнюю секцию,

вторая – среднюю, третья – нижнюю. Состояние каждой из секций

определяется ее цветом: black (черный), red (красный), yellow

(желтый) и green (зеленый). Если некоторый цвет мигает, то он

описывается в верхнем регистре, иначе – в нижнем.

Выходные данные. Вывести ответ на задачу в том же формате,

если светофор исправен. В случае неисправности светофора

выведите «error».

Примеры

№ Ввод Вывод

1 black black

black black

green GREEN

Page 20: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

20

2 black black

YELLOW YELLOW

black black

3 red error

yellow

green

Для хранения состояния секций светофора будем использовать

тип данных string

1 #include <iostream> 2 using namespace std; 3 main(){ 4 string a,b,c; 5 cin>>a>>b>>c;

6 if(a==”black”&&b==”black”&&c==”green”)

7 cout<<”black\nblack\nGREEN”;

8 else if(a==”black”&&b==”black”&&c==”GREEN”)

9 cout<<”black\nyellow\nblack”;

... // ещё 4 варианта

18 else

19 if(a==”black”&&b==”YELLOW”&&c==”black”)

20 cout<<”black\nYELLOW\nblack”;

21 else cout<<”error”; }

Page 21: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

21

Остальные задачи раздела «Условный оператор» решить

самостоятельно.

Тема «Шахматы». Тема «Алгебра и геометрия».

Задачи A..J Задачи A..I

A 1119 Ладья A 970 От перестановки что-то

меняется…

B 1120 Слон B 597 Внеземные гости

C 1121 Ферзь C 529 Длина отрезка

D 1122 Король D 26 Две окружности

E 1123 Конь E 28 Симметрия

F 1124 Пешка F 277 Школьная алгебра

G 35 Шахматное поле G 411 Квадратное уравнение

H 62 Клетки H 1477 Квадратов много не

бывает

I 763 Игра с ладьёй I 1314 Упаковка

J 1088 Шахматные

фигуры

Тема «Сложные задачи». Задачи A..D

A 296 Лиса Алиса и кот Базилио

B 499 Турист

C 664 Котлеты

D 162 Манхэттенский полицейский

Page 22: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

22

2. ЦИКЛИЧЕСКИЕ АЛГОРИТМЫ

2.1. ЦИКЛЫ С ПАРАМЕТРОМ

Сайт acmp, «Курсы/Язык программирования С++/ Операторы

цикла»

Тема «Цикл с параметром (for)». Задачи A..J

Задача А. Монетки (106)

На столе лежат n монеток. Некоторые из них лежат вверх решкой,

а некоторые – гербом. Определите минимальное число монеток,

которые нужно перевернуть, чтобы все монетки были повернуты

вверх одной и той же стороной.

Входные данные. Вводится натуральное число N (1 <= N <= 100)

– число монеток. В каждой из последующих N строк содержится

одно целое число – 1, если монетка лежит решкой вверх, и 0, если

вверх гербом.

Выходные данные. Минимальное количество монет, которые

нужно перевернуть.

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

5 2

1

0

1

1

0

Подсчитаем сумму входных чисел и сравним её с половиной

количества: 1 #include <iostream> 2 using namespace std; 3 main(){ 4 int i,n,a,s=0; 5 cin>>n; 6 for(i=0;i<n;i++){cin>>a; s+=a;} 7 cout<<(s<=n/2?s:n-s); }

Page 23: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

23

Задача В. Арбузы (81)

Иван Васильевич пришел на рынок и решил купить два арбуза:

один для себя, а другой для тещи. Понятно, что для себя нужно

выбрать арбуз потяжелей, а для тещи полегче. Но вот незадача:

арбузов слишком много, и он не знает, как же выбрать самый

легкий и самый тяжелый арбуз? Помогите ему!

Входные данные. Вводится одно число N – количество арбузов.

Вторая строка содержит N чисел, записанных через пробел. Здесь

каждое число – это масса соответствующего арбуза. Все числа

натуральные и не превышают 30000.

Выходные данные. Вывести два числа через пробел: массу арбуза,

который Иван Васильевич купит теще, и массу арбуза, который он

купит себе.

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

5 1 9

5 1 6 5 9

Типичная задача на поиск максимума и минимума. Сначала

выберем в качестве значений максимума и минимума значение

первого числа, затем при вводе очередных чисел будем уточнять

максимум и минимум:

1 #include <iostream> 2 using namespace std; 3 main() { 4 int n,i,a,mx,mn; 5 cin>>n>>mx; mn=mx; 6 for(i=2;i<=n;i++) { 7 cin>>a; 8 if(a>mx) mx=a; 9 else if(a<mn) mn=a; } 10 cout<<mn<<' '<<mx; }

Page 24: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

24

Указания к решению некоторых задач темы «Цикл с

параметром (for)»

C 35 Конечные

автоматы

Не забывать после печати очередного

результата переходить на новую строку:

cout<<d<<endl;

D 233 Автобусная

экскурсия

Сначала задать номер аварийного моста

k=0. В случае аварии запоминать в k

номер моста. В условие продолжения

цикла добавить проверку k:

for(i=1;i<=N&&k==0;i++). После выхода

из цикла печатать ответ в зависимости от

k.

E 131 Перепись Установить начальный возраст старшего

мужчины Vmax=0 и его номер Nmax=-1.

Обновлять эти параметры, если очередной

V>Vmax или V==Vmax и номер n<Nmax.

F 63 Загадка Запустить цикл по числу Х от 1 до

Х<=1000&&X*(S-X)!=P,

после чего вывести Х и S-X.

G 15 Дороги Т. к. в матрице каждая дорога отмечена

дважды, подсчитать сумму элементов

матрицы и напечатать её половину.

H 2 Сумма Использовать формулу суммы членов

арифметической прогрессии. Рассмотреть

случай N<0.

I 10 Уравнение Посчитать значения полинома при всех

целых значениях Х от -100 до 100.

J 264 Оттепель При положительной температуре

увеличивать на 1 счётчик тёплых дней,

проверяя, не превышена ли достигнутая

ранее продолжительность, и сбрасывать

счётчик в 0 при неположительной

температуре.

Page 25: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

25

2.2. ЦИКЛЫ С ПРЕДУСЛОВИЕМ

Сайт acmp, «Курсы/Язык программирования С++/ Операторы

цикла»

Тема «Цикл с предусловием (while)». Задачи A..I

Задача А. Список квадратов (1125)

Требуется вывести квадраты натуральных чисел, не

превосходящие числа N.

Входные данные. Вводится натуральное число N (N ≤ 109).

Выходные данные. Вывести все квадраты натуральных чисел, не

превосходящие N, в порядке возрастания через пробел.

Примеры

№ Ввод Вывод

1 10 1 4 9

2 50 1 4 9 16 25 36 49

1 #include <iostream> 2 using namespace std; 3 main(){ 4 int i=1,n; 5 cin>>n; 6 while(i*i<=n){ 7 cout<<i*i<<' '; 8 i++; } }

Задача В. Минимальный делитель (1126)

Найти наименьший натуральный делитель целого числа N,

отличный от 1.

Входные данные. Вводится целое число N (1 < N ≤ 106).

Выходные данные. Выводится ответ на задачу.

Примеры

№ Ввод Вывод

1 15 3

2 35 5

Page 26: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

26

1 #include <iostream> 2 using namespace std; 3 main(){ 4 int n,i=2; 5 cin>>n; 6 while(n%i)i++; 7 cout<<i; }

Задача Е. Числа Фибоначчи (147)

Последовательностью Фибоначчи называется последовательность

чисел a0, a1, ..., an, ..., где a0 = 0, a1 = 1, ak = ak-1 + ak-2 (k > 1). Найти

N-е число Фибоначчи.

Входные данные. Вводится целое число N (0 ≤ N ≤ 30).

Выходные данные. Вывести N-е число Фибоначчи.

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

7 13 1 #include <iostream> 2 using namespace std; 3 main(){ 4 int n,a=0,b=1,c=0,i=0; 5 cin>>n; 6 while(i<n){ 7 a=b; 8 b=c; 9 c=a+b; 10 i++; } 11 cout<<c; }

Решить задачи

C 1127 Список степеней двойки

D 692 Бинарные числа

F 271 Числа Фибоначчи-2

G 1129 Банковские проценты

I 272 Сумма максимума и минимума

Page 27: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

27

Задача H. Утренняя пробежка (1128)

В первый день спортсмен пробежал X километров. В каждый

последующий день он увеличивал пробег на 15% от предыдущего

дня. По данному числу Y требуется определить номер дня, в

который пробег спортсмена составил не менее Y км.

Входные данные. Вводятся два положительных вещественных

числа X и Y (X,Y ≤ 1000).

Выходные данные. Выводится целое число – номер дня, в который

спортсмен пробежал не менее Y километров.

Примеры

№ Ввод Вывод

1 10 20 6

2 1 1000 51

1 #include<iostream> 2 using namespace std; 3 main(){ 4 int k=1; float x,y; 5 cin>>x>>y; 6 while(x<y){ 7 k++; 8 x*=1.15; }

9 cout<<k; }

Сайт acmp, «Курсы/Язык программирования С++/ Операторы

цикла»

Тема «НОД и НОК». Задачи A..С

Задача А. НОД (148)

Даны два натуральных числа A и B. Требуется найти их

наибольший общий делитель (НОД).

Входные данные. В единственной строке записаны натуральные

числа A и B через пробел (A, B ≤ 109).

Выходные данные. Выведите НОД чисел А и В.

Page 28: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

28

Пример

Ввод Вывод

12 42 6

1 #include<iostream> 2 using namespace std; 3 main(){ 4 int a,b; 5 cin>>a>>b; 6 while(x*y) 7 if(a>b)a%=b; 8 else b%=a; 9 cout<<a+b; }

Указания к решению других задач темы

В 14 НОК НОК двух чисел равен их произведению,

делённому на их НОД;

С 394 Апельсины Необходимо получить из m апельсинов

всего НОК(n,m) долек, ответом будет

количество долек, полученное из одного

апельсина.

Page 29: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

29

2.3. ЦИКЛЫ С ПОСТУСЛОВИЕМ

Сайт acmp, «Курсы/Язык программирования С++/ Операторы

цикла»

Тема «Цикл с постусловием (do … while)». Задачи A..N

Задача А. Длина последовательности (1132)

Задана последовательность неотрицательных целых чисел.

Требуется определить длину последовательности,

завершающуюся первым встретившимся нолем (число 0 не входит

в последовательность).

Входные данные. Вводится последовательность неотрицательных

целых чисел, не превышающих значения 100. Гарантируется, что

во входных данных не более 100 чисел и среди них есть хотя бы

одно число 0.

Выходные данные. Вывести целое число – длину

последовательности.

Примеры

№ Ввод Вывод

1 1 7 9 0 5 3

2 1 2 3 4 5 0 6 7 0 8 9 10 5

1 #include <iostream> 2 using namespace std; 3 main(){ 4 int n=-1,a; 5 do{ cin>>a; n++; }while(a); 6 cout<<n; }

Решить задачи

B 1133 Сумма последовательности

C 1134 Среднее значение

D 1135 Количество чётных элементов

E 1136 Максимум последовательности

Page 30: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

30

Задача F. Элементы, большие предыдущего (1137)

Задана последовательность неотрицательных целых чисел.

Требуется определить количество элементов, которые больше

предыдущего, в последовательности, которая завершается первым

встретившимся нолем (число 0 не входит в последовательность).

Входные данные. Вводится последовательность неотрицательных

целых чисел, не превышающих значения 100. Гарантируется, что

во входных данных не более 100 чисел и среди них есть хотя бы

одно число 0.

Выходные данные. Выводится целое число – количество

элементов, больших предыдущего.

Примеры

№ Ввод Вывод

1 1 7 9 0 2

2 1 2 3 4 5 6 7 0 8 9 10 6

1 #include<iostream> 2 using namespace std; 3 main(){ 4 int a,b,k=0; 5 cin>>b; 6 do{ 7 a=b; 8 cin>>b; 9 if(b>a)k++; 10 }while(b); 11 cout<<k; }

Решить задачи

G 1138 Второй максимум

H 1139 Элементы, равные максимуму

I 1140 Сумма последовательности

K 1142 Монотонный фрагмент

L 1143 Локальные максимумы

Page 31: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

31

Задача J. Равные элементы (1141)

Дана последовательность натуральных чисел,

завершающаяся числом 0. Требуется определить, какое

наибольшее число подряд идущих элементов этой

последовательности равны друг другу.

Входные данные. Последовательность неотрицательных

целых чисел, не превышающих значения 100. Гарантируется,

что во входных данных не более 100 чисел и среди них есть хотя

бы одно число 0.

Выходные данные. Целое число – ответ на задачу.

Примеры

№ Ввод Вывод

1 1 7 7 9 1 0 2

2 1 2 3 3 3 3 4 5 3 4 0 5 4

1 #include<iostream> 2 using namespace std; 3 main(){ 4 int k=1,m=1,a,b; 5 cin>>b; 6 do{ a=b; 7 cin>>b; 8 if(a==b)k++; 9 else { 10 if(k>m)m=k; 11 k=1;} 12 }while(b); 13 cout<<m; }

Задача M. Расстояние между максимумами (1144)

Элемент последовательности называется локальным максимумом,

если он строго больше предыдущего и последующего элемента

последовательности. Первый и последний элемент

последовательности не являются локальными максимумами.

Задана последовательность натуральных чисел, завершающаяся

числом 0. Требуется определить наименьшее расстояние между

Page 32: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

32

двумя локальными максимумами последовательности

натуральных чисел, завершающейся числом 0.

Входные данные. Последовательность неотрицательных целых

чисел, не превышающих значения 100. Гарантируется, что во

входных данных не более 100 чисел и среди них есть хотя бы одно

число 0.

Выходные данные. Целое число – наименьшее расстояние между

двумя локальными максимумами. Если в последовательности нет

двух локальных максимумов, вывести число 0.

Примеры

№ Ввод Вывод

1 1 2 1 1 2 1 2 1 0 2

2 1 2 3 0 0

1 #include<iostream> 2 using namespace std; 3 main(){ 4 int k=0,m=0,n=0,x,y,z; 5 cin>>x>>y>>z; 6 do{ 7 k++; 8 if(x<y&&y>z){ 9 n++; 10 if(n>1&&(n==2||n>2&&k<m))m=k; 11 k=0; } 12 x=y; y=z; 13 cin>>z; 14 }while(z); 15 cout<<m; }

Решить задачи

G 1138 Второй максимум

H 1139 Элементы, равные максимуму

I 1140 Сумма последовательности

K 1142 Монотонный фрагмент

L 1143 Локальные максимумы

Page 33: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

33

Указание к решению задачи N. Стандартное отклонение (1145)

Если аккуратно преобразовать подкоренное выражение, станет

видно, что нужны две суммы – сумма элементов

последовательности и сумма квадратов элементов. Среднее

арифметическое лучше хранить в переменной типа double, для

вычисления квадратного корня использовать функцию sqrt, для

чего в начале программы указать библиотеку cmath строкой

#include<cmath>.

Page 34: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

34

2.4. БИНАРНЫЙ ПОИСК

Сайт acmp, «Курсы/Язык программирования С++/ Операторы

цикла»

Тема «Бинарный поиск». Задачи A..G

Задача А. Сложность бинарного поиска (1130)

Загадано число от 1 до N. За какое наименьшее количество

вопросов вида «Загаданное число больше числа X?»,

подразумевающих ответы «Да» или «Нет», гарантированно можно

отгадать число?

Входные данные. Натуральное число N (N ≤ 5*1018).

Выходные данные. Целое число – ответ на задачу.

Примеры

№ Ввод Вывод

1 2 1

2 6 3

1 #include<iostream>

2 using namespace std;

3 main(){

4 long long n;int r,k=0;

5 cin>>n;

6 while(n>1){

7 k++;n=(n+1)/2; }

8 cout<<k; }

Задача С. Угадай число (1465)

Это интерактивная задача.

Программа жюри загадывает целое число N (1 ≤ N ≤ 109), которое

ваша программа должна будет отгадать не более чем за 100

попыток. Вы можете делать запросы путем вывода числа из

возможного диапазона целых чисел. В ответ на каждый запрос

программа жюри будет сообщать результат сравнения загаданного

числа с числом в запросе.

Протокол взаимодействия. После каждого запроса целого числа X

вашей программе будет сообщен в новой строке результат

Page 35: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

35

сравнения вашего числа X с загаданным числом N, что выражается

выводом одного символа с переносом строки:

< : загаданное число строго меньше числа в запросе (N < X);

> : загаданное число строго больше числа в запросе (N > X);

= : загаданное число совпадает с числом в запросе (N = X), при

получении такого ответа ваша программа должна немедленно

завершиться.

Ваша программа должна произвести не больше 100 запросов.

Для корректной работы программы после каждой операции

вывода данных выводите перевод строки, а также очищайте буфер

вывода. Очистка буфера вывода в С/С++ производится

следующим образом: fflush(stdout) или cout.flush().

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

> 3

< 10

< 8

= 6

1 #include<iostream> 2 using namespace std; 3 main(){ 4 int X,L=1,R=1000000001; 5 char c; 6 do{ 7 X=(L+R)/2; 8 cout<<X<<endl;cout.flush(); 9 cin>>c; 10 if(c=='>')L=X;else R=X; 11 }while(c!='=');}

Решить задачи

B 1130 POBEDA-2014

D 267 Ксерокопии

E 1397 Космическое поселение

F 1211 Вырубка леса

Page 36: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

36

Задача G. Корень кубического уравнения (1131)

Дано кубическое уравнение ax3+bx2+cx+d=0 (a ≠ 0). Известно, что

у этого уравнения ровно один корень. Требуется его найти.

Входные данные. Четыре целых числа: a, b, c и d – коэффициенты

кубического уравнения, каждый из которых не превосходит 1000

по абсолютной величине.

Выходные данные. Корень кубического уравнения с точностью не

менее 3 знаков после запятой.

Примеры

№ Ввод Вывод

1 2 -6 6 -2 1

2 -1 -6 -12 -7 -1.0000

1 #include<iostream>

2 using namespace std;

3 int a,b,c,d;

4 main(){

5 cin>>a>>b>>c>>d;

6 double x,L=-10000,R=10000,FX,

7 FL=((a*L+b)*L+c)*L+d;

8 do{

9 x=(L+R)/2;

10 FX=((a*x+b)*x+c)*x+d;

11 if(FL*FX>0){L=x;FL=FX;}

12 else R=x;

13 }while(R-L>0.0001);

14 cout<<x;}

Page 37: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

37

3. ОБРАБОТКА СТРОК

3.1. СИМВОЛЫ

Сайт acmp, «Курсы/Язык программирования С++/ Строковые

типы данных»

Тема «Символьный тип (char)». Задачи A..N

Задача А. Цифра (1146)

Задан символ. Требуется определить: является ли он цифрой?

Входные данные. Вводится единственный символ (ASCII-код от

33 до 127).

Выходные данные. Вывести «Yes», если символ является цифрой,

и «No» в противном случае.

Примеры

№ Ввод Вывод

1 5 Yes

2 A No

1 #include<iostream> 2 using namespace std; 3 main(){ 4 char c; 5 cin>>c; 6 cout<<((c>='0'&&c<='9')?"Yes":"No"); }

Задача B. Верхний регистр (1147)

Задан символ. Если он является строчной буковой латинского

алфавита, то его нужно перевести в верхний регистр. В противном

случае символ следует оставить без изменений.

Входные данные. Вводится единственный символ (ASCII-код от

33 до 127).

Выходные данные. Один символ – исходный символ в верхнем

регистре.

Примеры

№ Ввод Вывод

1 a A

2 B B

Page 38: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

38

Учитываем, что коды строчных букв на 32 больше кодов

заглавных 1 #include<iostream> 2 using namespace std; 3 main(){ 4 char c; 5 cin>>c;

6 if(c>='a'&&c<='z')c-=32; 7 cout<<с; }

В задаче С. Смена регистра (1148) надо ещё заглавные буквы

превращать в строчные, добавляя к их кодам 32.

Задача D. Количество нулей (1149)

Дано натуральное число N. Требуется определить количество

нулей среди цифр данного числа.

Входные данные. Вводится натуральное число N (N ≤ 1030).

Выходные данные. Число нулей в числе N.

Примеры

№ Ввод Вывод

1 1024 1

2 102003000 6

Нельзя вводить исходное число в числовую переменную,

ведь оно может там не поместиться. Вводим цифры числа

посимвольно, пока не кончатся, сравнивая каждый введённый

символ с символом ‘0’:

1 #include<iostream> 2 using namespace std; 3 main(){ 4 char c; int k=0; 5 while(cin>>c) 6 if(c=='0')k++; 7 cout<<k; }

Page 39: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

39

Решить задачи

E 1150 Удаление цифр

F 1404 Простой шифр

G 1152 Вставка символов

H 297 Кругляши

I 1151 Пароль

J 1198 Генератор паролей

K 43 Нули

L 1153 Благозвучное слово

M 1154 IP-адрес

N 163 Уравнение для 5 класса!

Page 40: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

40

3.2. СТРОКИ

Сайт acmp, Курсы/Язык программирования С++/ Строковые

типы данных

Тема «Строковый тип (string)». Задачи A..С

Задача А. Клавиатура (66)

Для данной буквы латинского алфавита нужно вывести справа

стоящую букву на стандартной клавиатуре. При этом клавиатура

замкнута, т.е. справа от буквы «p» стоит буква «a», от буквы «l» –

буква «z», а от буквы «m» – буква «q».

Входные данные. Один символ — маленькая буква латинского

алфавита.

Выходные данные. Буква, стоящая справа от заданной буквы, с

учетом замкнутости клавиатуры.

Примеры:

№ Ввод Вывод

1 q w

2 t y

3 p a

4 m q

1 #include <iostream> 2 using namespace std; 3 main(){ 4 int i; char c; 5 string s="qwertyuiopasdfghjklzxcvbnm"; 6 cin>>c; 7 for(i=0;i<s.size();i++) 8 if(c==s[i]){cout<<s[(i+1)%26];break;} }

Задача B. Число Е (46)

Вывести округлённое до N знаков после десятичной точки число

Е. Считать, что число Е в точности равно

2.7182818284590452353602875.

Входные данные. Целое число N (0 ≤ N ≤ 25).

Page 41: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

41

Примеры:

№ Ввод Вывод

1 0 3

2 25 2.7182818284590452353602875

3 6 2.718282

1 #include <iostream> 2 using namespace std; 3 main(){ 4 int n,i; 5 string s="2.7182818284590452353602875"; 6 cin>>n; 7 if(n){ 8 for(i=0;i<n+1;i++)cout<<s[i];

9 if(n<25&&s[n+2]>'4')s[n+1]=s[n+1]+1;

10 cout<<s[n+1];}

11 else cout<<3; }

Задача C. Цветочки (504)

В рождественский вечер на окошке стояло три цветочка, слева

направо: герань, крокус и фиалка. Каждое утро Маша вытирала

окошко и меняла местами стоящий справа цветок с центральным

цветком. А Таня каждый вечер поливала цветочки и меняла

местами левый и центральный цветок. Требуется определить

порядок цветов ночью по прошествии K дней.

Входные данные. Натуральное число K – число дней (K <=1000).

Выходные данные. Три латинских буквы: «G», «C» и «V»

(заглавные буквы без пробелов), описывающие порядок цветов на

окошке по истечении K дней (слева направо). Обозначения: G –

герань, C – крокус, V – фиалка.

Примеры

№ Ввод Вывод

1 1 VGС

2 5 CVG

Page 42: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

42

1 #include<iostream> 2 using namespace std; 3 main(){ 4 int k; string s="GCV"; 5 cin>>k; 6 while(k){ k--; 7 swap(s[1],s[2]); 8 swap(s[0],s[1]);} 9 cout<<s; }

Сайт acmp, «Курсы/Язык программирования С++/ Условный

оператор». Тема «Простые сравнения».

Задача C. Счастливый билет (52)

Счастливым билетом называют такой билет с шестизначным

номером, где сумма первых трех цифр равна сумме последних

трех. Т.е. билет с номером 385916 – счастливый, т.к. 3+8+5=9+1+6.

Написать программу, которая проверяет счастливость билета.

Входные данные. Одно целое число N (0 ≤ N < 106).

Выходные данные. Вывести «YES», если билет с номером N

счастливый, и «NO» в противном случае.

Примеры

№ Ввод Вывод

1 385916 YES

2 123456 NO

Мы уже решали эту задачу помощью разбиения 6-значного

числа на отдельные цифры. Обработаем входные данные как

строку. 1 #include <iostream> 2 using namespace std; 3 main (){ 4 string n; 5 cin>>n; 6 if(s[0]+s[1]+s[2]==s[3]+s[4]+s[5])

7 cout<<"YES"; 8 else cout<<"NO"; }

Page 43: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

43

Решите подобным образом в той же теме задачу F (324)

Четырехзначный палиндром.

Тема «Строковый тип (string)». Задачи D..I

Решить задачи

D 6 Шахматы

E 44 Стрелки

G 283 Рунные слова

H 295 Шифровка

Указание к решению Задачи I. Золото племени АББА

Заведомо длинные числа следует вводить не в числовые

переменные, а в строковые. Затем следует сравнить строки по

длине, а в случае равенства длин строк – сравнить строки на

«больше – меньше» по значению.

Сайт acmp, Курсы/Язык программирования С++/ Строковые

типы данных. Тема «Строковый тип (string)».

Задача F. Измени порядок (1200)

На одном из предприятий установлена пропускная система,

которая ежедневно фиксирует порядок прихода сотрудников,

используя персональные магнитные карты.

Директора предприятия заинтересовал список сотрудников,

регулярно опаздывающих на работу в последнее время, в целях

последующего возможного их сокращения. Для этого он сделал

распечатку фамилий сотрудников за последние K дней. Распечатка

представляла собой K строк текста, в каждой из которых были

записаны сотрудники, упорядоченные по времени прихода. Но

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

интересовали опоздавшие сотрудники. Разработать конвертор

формата данных, изменяющий порядок списков сотрудников.

Входные данные. Первая строка содержит натуральное число K (K

≤ 10) – число дней. Далее идут K строк, в каждой из которых задана

последовательность фамилий сотрудников, разделенных ровно

одним пробелом, в порядке их прихода на работу в один из K дней.

Page 44: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

44

Общее число сотрудников на предприятии не превышает 100,

гарантируется, что каждый день на работу приходит хотя бы один

сотрудник. Фамилия сотрудника – последовательность символов

английского алфавита длиной от 1 до 100 символов.

Выходные данные. Выведите ровно K строк в формате, удобном

для отслеживания опаздывающих сотрудников.

Пример ввода

3

Ivanov Petrov Sidorov

Bistrov Shustrov Serednyakov Opozdalova

Kuznetsova Ostapenko

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

Sidorov Petrov Ivanov

Opozdalova Serednyakov Shustrov Bistrov

Ostapenko Kuznetsova

Будем считывать строки целиком вместе с разделяющими

слова пробелами с помощью функции getline, а затем разбирать их

на слова до пробелов. Выделенные слова будем добавлять к

строке-накопителю слева, меняя при этом порядок слов. 1 #include <iostream>

2 using namespace std;

3 main(){

4 int n; string s,t;

5 cin>>n;

6 getline(cin,s);

7 for(int i=0;i<n;++i){

8 getline(cin,s);

9 for(int j=s.size()-1;j>=0;--j)

10 if(s[j]!=' ') t=s[j]+t;

11 else if(!t.empty()){

12 cout<<t<<' '; t.clear(); }

13 if(!t.empty()){ cout<<t; t.clear(); }

14 cout<<endl; } }

В строке 6 функция getline «дочитывает» пустой конец

строки после значения переменной n, чтобы следующие строки в

цикле читались корректно.

Page 45: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

45

3.3. СТРОКОВЫЕ ПОТОКИ

Сайт acmp, Курсы/Язык программирования С++/ Строковые

типы данных

Тема «Строковый тип (string)».

Задача F. Измени порядок (1200)

Эту задачу мы уже решали через строку-накопитель. Решим

её через поток строк, используя потоковый ввод из прочитанной

функцией getline строки s для выделения отдельных слов t и

формирования в s строки вывода:

1 #include<iostream> 2 #include<sstream> 3 using namespace std; 4 main(){ 5 string s,t; int k; 6 cin>>k;

7 getline(cin,s);

8 while(k){ k--; 9 getline(cin,s); 10 stringstream stin(s); 11 s=""; 12 while(stin>>t)s=' '+t+s; 13 s.erase(0,1); 14 cout<<s<<endl; } }

Page 46: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

46

3.4. СИСТЕМЫ СЧИСЛЕНИЯ

Сайт acmp, Курсы/Язык программирования С++/ Строковые

типы данных

Тема «Системы счисления». Задачи А..I

Задача А. Единицы (22)

Найти количество единиц в двоичной записи заданного числа.

Входные данные. Целое число n (0 ≤ n ≤ 2×109).

Выходные данные. Целое число — количество двоичных единиц в

записи числа n.

Примеры

№ Ввод Вывод

1 5 2

2 7 3

1 #include<iostream>

2 using namespace std;

3 main(){

4 int n,k=0;

5 cin>>n;

6 while(n){

7 k+=n%2;

8 n/=2; }

9 cout<<k; }

Задача В. Несложное вычисление (59)

Задано натуральное число n. Необходимо перевести его в k-ичную

систему счисления и найти разность между произведением и

суммой его цифр в этой системе счисления.

Например, пусть n = 239, k = 8. Тогда представление числа n в

восьмеричной системе счисления — 357, а ответ на задачу равен 3

× 5 × 7 − (3 + 5 + 7) = 90.

Входные данные. Два натуральных числа: n и k (1 ≤ n ≤ 109, 2 ≤ k

≤ 10) в десятичной системе счисления.

Выходные данные. Ответ (в десятичной системе счисления).

Page 47: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

47

Примеры

№ Ввод Вывод

1 239 8 90

2 1000000000 7 -34

1 #include <iostream>

2 using namespace std;

3 main(){

4 int n,k,p=1,s=0;

5 cin>>n>>k;

6 while(n){

7 s+=n%k;

8 p*=n%k;

9 n/=k; }

10 cout<<p-s; }

Задача С. Unix (941)

Составить программу сложения двух чисел, представленных в

троичной системе счисления.

Входные данные. Два разделенных пробелом числа N и M (0 ≤ N,

M ≤ 231-1) в троичной системе счисления.

Выходные данные. Сумма N и M в десятичной системе счисления.

Примеры

№ Вввод Вывод

1 1 1 2

2 20 102 17

1 #include<iostream>

2 using namespace std;

3 main(){

4 string a,b;

5 long long n=0,m=0;

6 cin>>a>>b;

7 for(auto c:a)n=n*3+c-'0';

8 for(auto c:b)m=m*3+c-'0';

9 cout<<n+m;}

Page 48: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

48

Решить задачи

D 542 Бит-реверс

E 315 Наименьшая система счисления

F 173 Число-палиндром

G 208 Забавная игра

H 295 Делимость на 7

I 578 Система счисления

Page 49: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

49

4. ФУНКЦИИ

Сайт acmp, раздел «Курсы/Язык программирования С++/

Функции»

Тема «Функции-1». Задачи A..F

Задача А. Количество цифр (1225)

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

цифрами.

При решении данной задачи необходимо реализовать функцию

IsDigit(C), возвращающую 1, если символ C – цифра, и 0 – иначе.

Входные данные. Три символа, разделенные пробелом.

Гарантируется, что ASCII-коды символов превышают 32.

Выходные данные. Ответ на задачу.

Примеры

№ Ввод Вывод

1 А % 5 1

2 1 2 3 3

1 #include <iostream>

2 using namespace std;

3 int IsDigit(char c){

4 return(c>=’0’&&c<=’9’)?1:0; }

5 main(){

6 char a,b,c;

7 cin>>a>>b>>c;

8 cout<<IsDigit(a)+IsDigit(b)+IsDigit(c); }

Задача В. Подсчёт букв (1227)

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

буквами английского алфавита (в любом регистре).

При решении данной задачи реализовать функцию IsLetter(C),

возвращающую 1, если символ C – английская буква, и 0 – иначе.

Входные данные. Три символа, разделенные пробелом.

Гарантируется, что ASCII-коды символов превышают 32.

Выходные данные. Ответ на задачу.

Page 50: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

50

Примеры

№ Ввод Вывод

1 А % 5 1

2 А 2 b 2

Указание к решению. Используя текст предыдущей задачи,

написать функцию IsLetter с проверкой того, что символ с является

прописной или строчной буквой латинского алфавита.

Задача C. Число сочетаний (1227)

Факториал числа n, обозначаемый «n!» – произведение всех

натуральных чисел от 1 до n. Сочетанием из n по k называют набор

из k элементов, выбранных из данного множества, содержащего n

различных элементов. При этом наборы, отличающиеся только

порядком следования элементов, считаются одинаковыми.

Число возможных сочетаний из n по k вычисляется по формуле:

По заданным целым числам n и k требуется вычислить число

сочетаний.

При решении задачи реализовать функцию F(n), вычисляющую

факториал числа.

Входные данные. Целые числа n и k (0 ≤ k ≤ n ≤ 20).

Выходные данные. Число сочетаний из n по k.

Примеры

№ Ввод Вывод

1 3 2 3

2 7 3 35

!!! knknCkn

Page 51: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

51

1 #include<iostream> 2 using namespace std; 3 long long F(int n){ 4 long long f=1; 5 while(n>1){f*=n; n--;} 6 return f; } 7 long long C(int n,int k){

8 return F(n)/F(k)/F(n-k);}

9 main(){ 10 int n,k; 11 cin>>n>>k; 12 cout<<C(n,k); }

В строках 3..6 – итерационная реализация функции

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

реализация той же функции: long long F(int n){ return(n>1)?n*F(n-1):1; }

Задача D. Сумма простых чисел (1228)

Простым числом называют натуральное число, у которого ровно

два различных натуральных делителя. Другими словами, число

является простым, если оно больше единицы и делится нацело

только на себя и на единицу.

Дано три целых числа. Требуется определить, какие из заданных

чисел являются простыми, и вычислить их сумму. Также требуется

проверить, является ли полученная сумма простыми числом.

При решении данной задачи реализовать функцию IsPrime(N),

которая возвращает N, если N – простое число, и 0 – иначе.

Входные данные. Три целых числа, не превосходящие 1000 по

абсолютной величине.

Выходные данные. В первой строке выведите сумму,

составленную из простых чисел во входных данных. Если таковых

чисел нет, выведите 0. Во второй строке выведите «Yes», если

полученная сумма – простое число, и «No» – в противном случае.

Page 52: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

52

Примеры

№ Ввод Вывод

1 3 5 11 19

Yes

2 3 4 5 8

No

1 #include<iostream> 2 using namespace std; 3 int IsPrime(int n){ 4 if(n<2)return 0; 5 int k=2; 6 while(k*k<=n)if(n%k)k++;else n=0; 7 return n;} 8 main(){ 9 int i,c,n=0; 10 for(i=0;i<3;++i){cin>>c; n+=IsPrime(c));} 11 cout<<n<<endl<<(IsPrime(n)?"Yes":"No");}

Задача Е. Прямоугольный треугольник (1229)

Заданы целочисленные координаты вершин треугольника на

плоскости. Необходимо определить, является ли данный

треугольник прямоугольным.

Требуется решить данную задачу с использованием теоремы

Пифагора, вычислив квадраты длин сторон треугольника и

проверив условие: a2+b2=c2. При этом следует реализовать

функцию Side(a,b), вычисляющую квадрат длины отрезка между

парой точек.

Входные данные. 6 чисел через пробел, координаты вершин

треугольника в формате x1 y1 x2 y2 x3 y3. Все числа целые, не

превосходящие 1000 по абсолютной величине.

Выходные данные. Вывести «Yes», если треугольник является

прямоугольным, и «No» – в противном случае.

Page 53: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

53

Примеры

№ Ввод Вывод

1 0 3 0 0 5 0 Yes

2 0 0 1 5 2 0 No

1 #include <iostream>

2 using namespace std;

3 int Side(int x1,int y1,int x2,int y2){

4 return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);}

5 main(){

6 int x1,y1,x2,y2,x3,y3,a,b,c;

7 cin>>x1>>y1>>x2>>y2>>x3>>y3;

8 a=Side(x1,y1,x2,y2);

9 b=Side(x3,y3,x2,y2);

10 c=Side(x1,y1,x3,y3);

11 if(a+b==c||a+c==b||b+c==a)cout<<"Yes";

12 else cout<<"No";}

Задача F. Площадь треугольника (822)

По целочисленным координатам вершин треугольника (x1,y1),

(x2,y2) и (x3,y3) требуется вычислить его площадь.

Входные данные. 6 целых чисел x1,y1,x2,y2,x3,y3 – координаты

вершин треугольника. Все числа не превышают 106 по абсолютной

величине.

Выходные данные. Точное значение площади заданного

треугольника.

Примеры

№ Ввод Вывод

1 2 1 2 4 6 1 6

2 0 0 0 3 3 0 4.5

Для вычисления площади треугольника по координатам его

вершин можно было бы вычислить по теореме Пифагора длины

сторон треугольника, чтобы воспользоваться формулой Герона, но

более простым, быстрым и точным будет использование формулы

вычисления векторного произведения:

Page 54: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

54

S=| (x2-x1)(y3-y1)-(x3-x1)(y2-y1)/2 | .

Во избежание переполнения координаты будем хранить не в

целых, а в вещественных переменных. Для вычисления модуля

вещественного числа придётся подключить математическую

библиотеку cmath.

1 #include <iostream>

2 #include <cmath> 3 using namespace std; 4 float Area(float x1,float y1,float x2, 5 float y2,float x3,float y3){ 6 return fabs((x2-x1)*(y3-y1)- 7 (x3-x1)*(y2-y1))/2.; } 8 main(){ 9 float x1,y1,x2,y2,x3,y3; 10 cin>>x1>>y1>>x2>>y2>>x3>>y3; 11 cout<<fixed<<Area(x1,y1,x2,y2,x3,y3); }

Тема «Функции-2». Указания к решению задач A, С, D, Е

А 327 В одном

шаге от

счастья

Учесть, что номеру 0 (000000)

предшествует номер 999999, а после

номера 999999 идёт номер 0 (000000).

Использовать решение задачи

«Счастливый билет» из темы «Условный

оператор».

С 323 Гипотеза

Гольдбаха

Использовать функцию IsPrime из задачи

«Сумма простых чисел» из темы

«Функции-1»

D 164 Счастливый

билет-2

Хранить число в строке, разбивать её на

две части в цикле, удлиняя левую часть и

укорачивая правую. Для вычисления

цифрового корня части строки составить

функцию, возможно, рекурсивную.

Page 55: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

55

E 102 Треугольник

и точка

Если точка 4 находится внутри (или на

одной из сторон) треугольника 123, то

сумма площадей треугольников 412, 413,

423 должна быть равна площади

треугольника 123. Использовать функцию

Area из задачи «Площадь треугольника»

из темы «Функции-1»

Page 56: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

56

5. ОДНОМЕРНЫЕ МАССИВЫ

5.1. ПРОСТОЙ ПРОХОД ПО МАССИВУ

Сайт acmp, раздел «Курсы/Язык программирования С++/

Массивы»

Тема «Линейный поиск». Задачи A..F

Задача А. Линейный поиск (1214)

Вычислить, сколько раз встречается некоторое число X в массиве

A[1..N].

Входные данные. В первой строке содержится натуральное число

N – количество элементов в массиве. Во второй строке записаны

N целых чисел Ai, разделенные пробелом. Третья строка содержит

число X. Все числа во входных данных не превосходят 1000 по

абсолютной величине.

Выходные данные. Количество вхождений числа X в массив A.

Примеры

№ Ввод Вывод

1 5 1

1 2 3 4 5

3

2 7 3

5 3 4 5 5 2 1

5

Задачу можно решать по-разному. Первый способ –

заполнить массив данными и последовательно искать в нём

заданное число: 1 #include <iostream> 2 using namespace std; 3 main(){ 4 int N; 5 cin>>N;

6 int A[N],X,i,k=0;

7 for(i=0;i<N;i++)cin>>A[i]; 8 cin>>X; 9 for(i=0;i<N;i++)if(A[i]==X)k++; 10 cout<<k; }

Page 57: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

57

Второй способ – создать массив счётчиков. Индекс будет

указывать на то, какое число встретилось, а значение элемента

массива с этим индексом – сколько раз это число встретилось:

1 #include<iostream> 2 using namespace std; 3 main(){ 4 int A,B[2001]={0},N,i,X; 5 cin>>N; 6 for(i=0;i<N;i++){ 7 cin>>A; 8 B[A+1000]++;} 9 cin>>X; 10 cout<<B[X+1000];}

Задача В. Максимальный элемент (1216)

В целочисленном массиве A[1..N] на отрезке [L,R] необходимо

найти максимальный элемент и его номер.

Входные данные. Первая строка содержит натуральное число N –

количество элементов в массиве. Во второй строке записаны N

целых чисел Ai, разделенные пробелом. Третья строка содержит

два натуральных числа L и R, которые задают отрезок поиска [L,R]

(-1000 ≤ Ai ≤ 1000, 1 ≤ L ≤ R ≤ N ≤ 1000).

Выходные данные. Значение максимального элемента массива на

отрезке [L,R] и его индекс. В случае неоднозначности определения

индекса следует вывести наименьший из них.

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

5 7 4

1 3 5 7 9

2 4

Page 58: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

58

Учитываем, что массивы в С++ индексируются с 0:

1 #include<iostream> 2 using namespace std; 3 main(){ 4 int N; 5 cin>>N;

6 int A[N+1],L,R,i,k

7 for(i=1;i<=N;i++)cin>>a[i]; 8 cin>>L>>R; 9 k=L; 10 for(i=L+1;i<=R;i++) if(a[i]>a[k]) k=i; 11 cout<<a[k]<<' '<<k; }

Решить задачи

C 1217 Контроперация

D 496 Сбор черники

F 293 Налоги

Задача Е. Ближайшее число

Требуется найти в массиве A[1..N] самый близкий по величине

элемент к заданному числу X.

Входные данные. Первая строка содержит натуральное число N –

количество элементов в массиве. Во второй строке записаны N

целых чисел Ai, разделенные пробелом. Третья строка содержит

число X. Все числа во входных данных не превосходят 1000 по

абсолютной величине.

Выходные данные. Значение элемента массива, ближайшее к X.

Если таких значений несколько, следует вывести наименьшее

среди них.

Примеры

№ Ввод Вывод

1 5 5

1 2 3 4 5

6

Page 59: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

59

№ Ввод Вывод

2 5 3

5 4 3 2 1

3

1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4 main(){ 5 int n; 6 cin>>n;

7 int a[n],x,i,y 8 for(i=0;i<n;i++)cin>>a[i]; 9 cin>>x; 10 y=a[0]; 11 for(i=1;i<n;i++) 12 if(abs(a[i]-x)<abs(y-x)|| 13 abs(a[i]-x)==abs(y-x)&&a[i]<y) y=a[i];

14 cout<<y; }

Page 60: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

60

5.2. ПРЕОБРАЗОВАНИЯ МАССИВОВ

Сайт acmp, раздел «Курсы/Язык программирования С++/

Массивы»

Тема «Преобразования и анализ данных». Задачи A..J

Задача А. Разворот (149)

Дано натуральное число N и последовательность из N элементов.

Требуется вывести эту последовательность в обратном порядке.

Входные данные. В первой строке - натуральное число N (N ≤

1000). Во второй строке через пробел идут N целых чисел, по

модулю не превосходящих 1000 - элементы последовательности.

Выходные данные. Выведите заданную последовательность в

обратном порядке.

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

3 3 2 1

1 2 3

Выполним указания буквально: 1 #include <iostream>

2 using namespace std;

3 main(){

4 int n,i;

5 cin>>n; int a[n];

6 for(i=0;i<n;i++)cin>>a[i];

7 for(i=n-1;i>=0;i--)cout<<a[i]<<' '; }

Другой способ заключается в изменении массива: 1 #include <iostream>

2 using namespace std;

3 main(){

4 int n,i;

5 cin>>n; int a[n];

6 for(i=0;i<n;i++)cin>>a[i];

7 for(i=0;i<n/2;i++)swap(a[i],a[n-1-i]);

8 for(auto b:a)cout<<b<<' '; }

Page 61: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

61

Эта задача может быть решена также с помощью рекурсии и

с помощью стека

Решить задачи

B 284 Подмассив массива

C 1218 Шеренга

D 1219 Двойной переворот

Задача Е. Сдвиг перестановки (392)

Перестановкой порядка n называется последовательность из

попарно различных целых положительных чисел p1, p2, ... , pn, где

каждое 1 <= pi <= n. Будем говорить, что перестановка q1, q2, ... , qn

лексикографически меньше перестановки p1,p2,...,pn, если

существует такое i, что qi < pi, а для любого j < i pj = qj .

Циклическим сдвигом на k перестановки p1, p2, ... , pn называется

последовательность, pk+1, pk+2, ... , pn, p1, ... , pk. Отметим, что любой

циклический сдвиг перестановки также является перестановкой.

Найти лексикографически наименьший циклический сдвиг

заданной перестановки.

Входные данные. Первая строка содержит порядок n (1 <= n <=

105) заданной перестановки. Вторая строка содержит числа p1, p2,

... , pn, отделенные друг от друга пробелами.

Выходные данные. Выведите перестановку, являющуюся

лексикографически наименьшим циклическим сдвигом исходной

перестановки.

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

3 1 3 2

3 2 1

Page 62: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

62

1 #include<iostream>

2 using namespace std;

3 main(){

4 int n,i,m=0;

5 cin>>n; int a[n];

6 for(i=0;i<n;i++){

7 cin>>a[i];

8 if(a[i]<a[m])m=i;}

9 for(i=m;i<n;i++)cout<<a[i]<<' ';

10 for(i=0;i<m;i++)cout<<a[i]<<' '; }

Решить задачи

F 1220 Суперсдвиг

G 5 Статистика

H 9 Домашнее задание

I 39 Волосатый бизнес

J 82 Пересечение множеств

Page 63: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

63

5.3. СТРУКТУРЫ И МАССИВЫ СТРУКТУР

Сайт acmp, раздел «Курсы/Язык программирования С++/

Функции»

Тема «Функции-1». Задача Е. Прямоугольный треугольник

(1229)

Заданы целочисленные координаты вершин треугольника на

плоскости. Необходимо определить, является ли данный

треугольник прямоугольным.

Требуется решить данную задачу с использованием теоремы

Пифагора, вычислив квадраты длин сторон треугольника и

проверив условие: a2+b2=c2. При этом следует описать структуру

Point для хранения координат точки на плоскости, а также

функцию Side(a,b), вычисляющую квадрат длины отрезка между

парой точек.

Входные данные. Координаты вершин треугольника в формате x1

y1 x2 y2 x3 y3 через пробел.

Выходные данные. «Yes», если треугольник является

прямоугольным и «No» в противном случае.

Примеры

№ Ввод Вывод

1 0 3 0 0 5 0 Yes

2 0 0 1 5 2 0 No

1 #include <iostream> 2 using namespace std; 3 struct Point{int x;int y;}; 4 int Side(Point A,Point B){ 5 return (A.x-B.x)*( A.x-B.x)+ 6 ( A.y-B.y)*( A.y-B.y); } 7 main(){ 8 Point A,B,C;int a,b,c; 9 cin>>A.x>>A.y>>B.x>>B.y>>C.x>>C.y; 10 a=Side(B,C); b=Side(A,C); c=Side(A,B); 11 if(a+b==c||a+c==b||b+c==a) cout<<"Yes";

12 else cout<<"No"; }

Page 64: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

64

Сайт acmp, раздел «Курсы/Язык программирования С++/

Массивы»

Тема «Массивы структур». Задачи B,C

Задача В. Точки на плоскости (1223)

На плоскости заданы N точек с целочисленными координатами.

Требуется найти среди них пару самых ближних и пару самых

дальних друг от друга точек.

Входные данные. Первая строка содержит целое число N (2 ≤ N ≤

1000) – количество точек. Далее следуют N строк пар целых чисел

(Xi,Yi), описывающих координаты первой, второй и т.д. точек

соответственно (-109 ≤ Xi,Yi ≤ 109).

Выходные данные. В первой строке выведите через пробел номера

пары ближних друг к другу точек. Во второй строке выведите

номера пары дальних друг от друга точек. В случае

неоднозначности определения ответа выведите любой.

Примеры

№ Ввод Вывод

1 5 1 2

0 0 3 4

1 2

-3 4

9 6

5 -2

2 10 4 9

3 8 7 10

-2 5

9 -3

0 0

6 8

-5 4

9 0

2 -6

-1 -1

-9 7

Page 65: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

65

Воспользуемся структурой Point и функцией Side из

вышеописанной задачи и организуем перебор всех пар точек с

учётом нумерации с 0 и с 1:

1 #include <iostream>

2 using namespace std;

3 struct Point{int x;int y;};

4 int Side(Point A,Point B){

5 return (A.x-B.x)*( A.x-B.x)+

6 ( A.y-B.y)*( A.y-B.y); }

7 main(){

8 int i,j,n,m,mx,mn,p=1,q=2,r=1,s=2;

9 cin>>n; Point a[n];

10 for(i=0;i<n;++i)cin>>a[i].x>>a[i].y;

11 mn=Side(a[0],a[1]); mx=mn;

12 for(i=0;i<n-1;++i)for(j=i+1;j<n;++j){

13 m=Side(a[i],a[j]);

14 if(m<mn){mn=m;p=i+1;q=j+1;}

15 else if(m>mx){mx=m;r=i+1;s=j+1;} }

16 cout<<p<<' '<<q<<endl<<r<<' '<<s; }

Увы, при попытке сдать эту программу мы получим

результат «Wrong answer» - «неверный ответ» на 11-м тесте.

Очевидно, причина - в переполнении при возведении в квадрат

больших чисел порядка 109. Заменим тип int на long long для полей

структуры Point, функции Side и переменных m, mn, mx, и всё у

нас получится. Если вместо long long использовать double, задача

тоже будет принята, но с более чем вдвое большим временем.

Задача С. Лучшие из лучших (1224)

В классе N учеников. По окончании года всем выставили итоговые

оценки по M предметам. Требуется определить тройку лучших

учащихся по среднему баллу.

Входные данные. Первая строка содержит два целых числа N (3 ≤

N ≤ 1000) и M (1 ≤ M ≤ 20) – количество учеников и число

Page 66: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

66

предметов соответственно. Далее следует N пар строк о каждом

ученике в следующем формате:

<Фамилия> <Имя>

< A1 > < A2 > … < AM >

Оценки Ai – целые числа от 2 до 5, разделенные пробелом.

Гарантируется, что длина каждой из строк входного файла не

превосходит 50 символов.

Выходные данные. Список трех лучших учеников по среднему

баллу. Если среди остальных учеников есть ученики, набравшие

тот же балл, что и один из трех лучших, то следует вывести и их.

Данные учеников следует выводить согласно примерам, в той же

очередности, в которой они идут во входных данных.

Примеры

№ Ввод Вывод

1 5 4

Dmitriev Maksim

2 2 5 2

Petrov Artur

4 4 5 2

Kuznetsova Elena

3 3 4 3

Popov Alexandr

5 4 3 2

Ivanova Svetlana

3 2 5 5

Petrov Artur (4 4 5 2)

Popov Alexandr (5 4 3 2)

Ivanova Svetlana (3 2 5 5)

2 4 3

Voronov Andrey

4 3 5

Korovina Alexandra

3 3 3

Antipov Anton

5 5 2

Stepanova Irina

3 3 3

Voronov Andrey (4 3 5)

Korovina Alexandra (3 3 3)

Antipov Anton (5 5 2)

Stepanova Irina (3 3 3)

Page 67: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

67

Указания к решению задачи.

Нужно описать структуру вида: struct Pupil{

string f; string n; int b[20]; int s;};

для хранения в соответствующем массиве структур для каждого

ученика его фамилии, имени, оценок и суммарного балла (вместо

среднего), вычисляя значение поля s в ходе ввода оценок и

используя его в дальнейшем при анализе и отборе данных.

Page 68: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

68

6. СОРТИРОВКИ МАССИВОВ

6.1. КВАДРАТИЧНЫЕ СОРТИРОВКИ

Сайт acmp, раздел «Курсы/Язык программирования С++/

Сортировка»

Тема «Квадратичная сортировка». Задачи A..I

Задача A. Сортировка выбором (1230)

Задан целочисленный массив, состоящий из N элементов.

Требуется упорядочить в нем элементы по неубыванию, используя

сортировку выбором (SelectSort).

Входные данные. В первой строке – натуральное число N –

количество элементов в массиве (N ≤ 1000). Во второй строке – N

целых чисел, не превосходящих 109 по абсолютной величине.

Выходные данные. N чисел – элементы массива, упорядоченные

по неубыванию.

Примеры

№ Ввод Вывод

1 3 2 5 7

7 2 5

2 10 4 5 7 11 12 18 32 48 74 92

12 7 92 5 18 4 32 48 11 74

1 #include<iostream>

2 using namespace std;

3 void SelectSort(int a[],int n){

4 int i,j;

5 for(i=0;i<n-1;++i)

6 for(j=i+1;j<n;++j)

7 if(a[j]<a[i])swap(a[i],a[j]);}

8 main(){

9 int i,n;cin>>n;int a[n];

10 for(i=0;i<n;++i)cin>>a[i];

11 SelectSort(a,n);

12 for(auto b:a)cout<<b<<' ';}

Page 69: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

69

Задача B. Сортировка пузырьком (1231)

Задан целочисленный массив, состоящий из N элементов.

Требуется посчитать число инверсий (обмена значений соседних

элементов массива) в процессе сортировки элементов массива по

неубыванию при использовании алгоритма сортировки

«пузырьком» (BubbleSort).

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

Первая строка входного файла INPUT.TXT содержит натуральное

число N – количество элементов в массиве (N ≤ 1000). Во второй

строке содержатся N целых чисел, не превосходящих 109 по

абсолютной величине.

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

В выходной файл OUTPUT.TXT выведите целое число –

количество инверсий в процессе сортировки методом «пузырька».

Примеры

№ Ввод Вывод

1 3 2

7 2 5

2 10 18

12 7 92 5 18 4 32 48 11 74

Составим функцию, не только сортирующую массив

пузырьком, но и возвращающую количество произведённых при

этом обменов. 1 #include<iostream>

2 using namespace std;

3 int BubbleSort(int a[],int n){

4 int i,j=0,k=0;bool f;

5 do{f=false;

6 for(i=n-1;i>j;--i)if(a[i]<a[i-1]){

7 swap(a[i],a[i-1]); k++;f=true;}

8 j++;}while(f);

9 return k;}

10 main(){ int i,n;cin>>n;int a[n];

11 for(i=0;i<n;++i)cin>>a[i];

12 cout<<BubbleSort(a,n);}

Page 70: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

70

Задача С. Азартный Шрэк (1231)

На игровом столе лежат N карточек. На каждой карточке написано

целое положительное число. Игра проходит между игроком и

крупье. Карточки лежат на столе числами вниз. Игра заключается

в том, что игрок открывает ровно N/2 карточек. Сумма всех чисел,

написанных на карточках, открытых игроком, называется “суммой

игрока”. Следующим ходом крупье открывает оставшиеся N/2

карточек. Сумма всех чисел, написанных на карточках, открытых

крупье, называется “суммой крупье”. Выигрыш игрока

определяется разностью чисел между “суммой игрока” и “суммой

крупье”. Очевидно, что полученная разность может быть

отрицательным числом. Это свидетельствует о том, что игрок

проиграл и должен казино соответствующую сумму.

Определить максимальную сумму выигрыша, которую может

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

числа, написанные на карточках.

Входные данные. Первая – одно четное натуральное число N (2 ≤

N ≤ 100). Вторая строка содержит ровно N чисел Ai(1 ≤ Ai ≤ 106) –

числа, написанные на игральных карточках. Все числа в строке

разделяются одиночными пробелами, Ai – число, написанное на i-

й карточке. Карточки нумеруются последовательно, начиная с

единицы.

Выходные данные. Одно целое число – максимальный выигрыш.

Примеры

№ Ввод Вывод

1 2 2

1 3

2 4 104

3 1 8 100

Отсортируем карточки методом вставки и сравним суммы

большей и меньшей половин.

Page 71: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

71

1 #include<iostream>

2 using namespace std;

3 void InsertSort(int a[],int n){

4 for(int i=1,j=1;i<n;++i,j=i)

5 while(j&&a[j]<a[j-1]){

6 swap(a[j],a[j-1]);j--;}}

7 int Sum(int a[],int n){

8 int s=0,i;

9 for(i=0;i<n;++i)s+=a[i];

10 return s;}

11 main(){

12 int n,i;

13 cin>>n;int a[n];

14 for(i=0;i<n;++i)cin>>a[i];

15 InsertSort(a,n);

16 cout<<Sum(a+n/2,n/2)-Sum(a,n/2);}

Решить задачи

D 119 Сортировка времени

E 461 Выборы

F 174 Свадьба

G 32 Годовой баланс

H 252 Сортировка масс

I 184 Рабочее время

Page 72: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

72

6.2. БЫСТРЫЕ СОРТИРОВКИ

Для решения последующих задач полезно отработать

основные алгоритмы быстрых сортировок, рассмотренные на

лекциях. Проверить их можно на задаче «Сортировка выбором»

(1230) из темы «Квадратичная сортировка», заменяя текст

соответствующей функции.

Сортировка Шелла

void ShellSort(int a[],int n){

int i,j,k=n/2;

while(k){

for(i=k;i<n;i++){

j=i-k;

while(j>=0)

if(a[j]>a[j+k]){

swap(a[j],a[j+k]); j-=k;}

else j=-1;}

k/=2;} }

Пирамидальная сортировка Уильямса

void HeapSort(int a[],int n){

int i,j,k;

for(i=n/2-1;i>=0;i--){

j=i;

while(j<n/2){ k=2*j+1;

if(k+1<n&&a[k]<a[k+1])k++;

if(a[k]>a[j]){swap(a[k],a[j]); j=k;}

else break; } }

for(i=n-1;i>0;i--){

j=0; swap(a[0],a[i]);

while(j<i/2){ k=2*j+1;

if(k+1<i&&a[k]<a[k+1])k++;

if(a[k]>a[j]){swap(a[k],a[j]); j=k;}

else break; } } }

Page 73: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

73

Быстрая сортировка Хоара

void QuickSort(int a[],int n){

if(n<2)return;

int L=0,R=n-1,m=a[n/2];

do{while(a[L]<m)L++; while(a[R]>m)R--;

if(L<=R){swap(a[L],a[R]); L++; R--;}

}while(L<=R);

QuickSort(a,R+1); QuickSort(a+L,n-L); }

Сортировка слиянием фон Неймана

void MergeSort(int a[],int n){

if(n<2)return;

int m=n/2,i=0,j=m,k=0,b[n];

MergeSort(a,m); MergeSort(a+m,n-m);

while(i<m&&j<n)

if(a[i]<a[j]){b[k]=a[i]; i++;k++;}

else {b[k]=a[j]; j++;k++;}

while(i<m){b[k]=a[i]; i++;k++;}

while(j<n){b[k]=a[j]; j++;k++;}

for(i=0;i<n;++i)a[i]=b[i]; }

Сайт acmp, раздел «Курсы/Язык программирования С++/

Сортировка»

Тема «Быстрая сортировка». Задачи B..D

Задача B. Арифметическая прогрессия - 2 (475)

Задана последовательность натуральных чисел из диапазона [1,

2147483647]. Необходимо определить: можно ли выстроить эти

числа в отрезок арифметической прогрессии. При необходимости

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

Входные данные. Последовательность натуральных чисел.

Количество чисел в последовательности может быть от 2 до 100

000. Числа разделены пробелами или символами перехода на

новую строку.

Page 74: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

74

Выходные данные. «Yes» в случае положительного ответа, либо

«No» в противоположном случае.

Примеры

№ Ввод Вывод

1 80 50 10 30 70 40 20 60 90 Yes

2 1 2 3 5 No

1 #include<iostream>

2 using namespace std;

3 void Quick(int a[],int n){

4 if(n<2)return;

5 int L=0,R=n-1,m=a[n/2];

6 do{while(a[L]<m)L++;while(a[R]>m)R--;

7 if(L<=R){swap(a[L],a[R]);L++;R--;}

8 }while(L<=R);

9 Quick(a,R+1);Quick(a+L,n-L); }

10 main(){

11 int n=0,d,f=1,i;

12 while(cin>>a[n])n++; int a[n];

13 Quick(a,n);

14 d=a[1]-a[0];

15 for(i=2;f&&i<n;i++)if(a[i]-a[i-1]!=d)f=0;

16 if(f)cout<<"Yes";else cout<<"No"; }

Задача C. Ближайшие точки (344)

На числовой прямой задано n точек. Необходимо найти среди них

две ближайшие.

Входные данные. Первая строка содержит количество точек n (2 ≤

n ≤ 105). Вторая строка содержит n различных целых чисел xi –

координаты заданных точек числовой прямой. Числа в строке

разделены пробелом. Значения всех координат xi не превосходят

109 по абсолютной величине.

Выходные данные. В первой строке вывести минимальное

расстояние между двумя точками. Во второй строке выходного

файла необходимо вывести номера точек, которым соответствует

найденное расстояние. Точки нумеруются натуральными числами

от 1 до n в том порядке, в котором они заданы во входном файле.

Page 75: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

75

Если ответов несколько, выведите тот из них, в котором точки

расположены левее других на числовой прямой. Первым

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

точки.

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

5 1

10 3 6 2 5 4 2

Чтобы не потерять первичные номера точек при сортировке,

будем хранить их вместе с координатами в соответствующей

структуре. 1 #include<iostream>

2 using namespace std;

3 struct Point{int x;int y;};

4 void MergeSort(Point a[],int n){

5 if(n<2)return;

6 int m=n/2;

7 MergeSort(a,m);MergeSort(a+m,n-m);

8 int i=0,j=m,k=0;Point b[n];

9 while(i<m&&j<n)

10 if(a[i].x<a[j].x){b[k]=a[i];k++;i++;}

11 else {b[k]=a[j];k++;j++;}

12 while(i<m){b[k]=a[i];k++;i++;}

13 while(j<n){b[k]=a[j];k++;j++;}

14 for(i=0;i<n;++i)a[i]=b[i];}

15 main(){

16 int n,i,d,j=0;

17 cin>>n; Point a[n];

18 for(i=0;i<n;++i){

19 cin>>a[i].x;a[i].y=i+1;}

20 MergeSort(a,n);

21 d=a[j+1].x-a[j].x;

22 for(i=1;i<n-1;++i)

23 if(a[i+1].x-a[i].x<d){

24 j=i; d=a[i+1].x-a[i].x;}

25 cout<<d<<endl<<a[j].y<<' '<<a[j+1].y;}

Page 76: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

76

Задача D. Преобразование последовательности (178)

Задана последовательность, содержащая n целых чисел.

Необходимо найти число, которое встречается в этой

последовательности наибольшее количество раз, а если таких

чисел несколько, то найти минимальное из них, и после этого

переместить все такие числа в конец заданной

последовательности. Порядок расположения остальных чисел

должен остаться без изменения.

Например, последовательность 1, 2, 3, 2, 3, 1, 2 после

преобразования должна превратиться в последовательность 1, 3, 3,

1, 2, 2, 2.

Входные данные. Первая строка содержит число n — количество

чисел во входной последовательности (3 ≤ n ≤ 200000). Следующая

строка содержит входную последовательность, состоящую из n

целых чисел, не превышающих по модулю 106. Все числа в строке

разделены пробелом.

Выходные данные. Выводится последовательность чисел, которая

получается в результате названного преобразования. Все числа в

последовательности должны быть разделены пробелом.

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

7 1 3 3 1 2 2 2

1 2 3 2 3 1 2

Указание к решению задачи. Следует при вводе сохранять последовательность в основном

массиве и в массиве-копии. Затем отсортировать основной массив

и, пройдя по нему, найти самую длинную цепочку одинаковых

элементов. Затем при выводе неотсортированной копии

пропускать вывод самого частого элемента и вывести все

пропущенные элементы потом.

Page 77: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

77

6.3. ЛИНЕЙНЫЕ СОРТИРОВКИ

Сайт acmp, раздел «Курсы/Язык программирования С++/

Сортировка»

Тема «Быстрая сортировка». Задача А. Сортировка подсчётом

(41)

Известно, что перепады температур колеблются от -100 до 100

градусов. Специалистам удалось выяснить значения температур в

N точках, температуры округлены до целых чисел. Упорядочить

температуры по неубыванию.

Входные данные. В первой строке задано натуральное число N -

количество участков (N ≤ 106). Во второй строке через пробел

записаны целые значения температур этих участков, не

превосходящие 100 по абсолютной величине.

Выходные данные. В единственную строку вывести разделенные

пробелом значения температур всех известных участков, которые

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

Примеры

№ Ввод Вывод

1 3 -20 9 14

9 -20 14

2 10 4 5 7 11 12 18 32 48 74 92

12 7 92 5 18 4 32 48 11 74

Поскольку возможно не более 201 разных значений,

создадим соответствующий массив счётчиков, не забыв заполнить

его нулями. Чтобы уложиться в ограничения по времени, вместо

потоков используем функции форматного ввода-вывода.

1 #include<stdio.h>

2 main(){

3 int n,t,c[201]={0};

4 scanf("%d",&n);

5 for(i=0;i<n;++i){

6 scanf("%d",&t); c[t+100]++;}

7 for(i=0;i<201;++i)

8 while(c[i]){

9 printf("%d ",i-100); c[i]--;}}

Page 78: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

78

Более обстоятельная и заведомо устойчивая сортировка

подсчётом предусматривает преобразование счётчиков в

диапазоны новых адресов для сортируемых элементов.

void count(int a[],int n,int k){

int b[n],c[k],i;

for(i=0;i<k;++i)c[i]=0;

for(i=0;i<n;++i)c[a[i]]++;

for(i=1;i<k;++i)c[i]+=c[i-1];

for(i=n-1;i>=0;--i){

c[a[i]]--;

b[c[a[i]]]=a[i];}

for(i=0;i<n;++i)a[i]=b[i]; }

Используем этот подход в поразрядной сортировке по

старшим разрядам в решении следующей задачи.

Сайт acmp, раздел «Курсы/Язык программирования С++/

Массивы». Тема «Массивы структур».

Задача А. Телефонный справочник (1222)

Есть телефонный справочник с информацией о номерах телефонов

и адресов абонентов. Реализовать эффективную структуру

данных, реализующую поиск информации об абонентах по

номерам телефонов.

Входные данные. Первая строка содержит два натуральных числа

N и M (N,M ≤ 30 000) – количество абонентов и количество

запросов по номеру телефона соответственно. Далее в 3∙N строках

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

каждом из абонентов занимает 3 строки и имеет вид:

<номер телефона>

<фамилия> <имя> <отчество>

<улица> <дом>-<квартира>

Где «номер телефона» – целое число, состоящее из 6 цифр. Здесь

«дом» и «квартира» – натуральные числа, не превосходящие 100.

Все строки во входных данных состоят не более чем из 50

символов.

Page 79: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

79

Далее следуют M строк с информацией о номерах телефонов

абонентов, информацию о которых необходимо получить.

Гарантируется, что все номера телефонов присутствуют в

телефонном справочнике.

Выходные данные. Для каждого номера телефона в запросе

вывести информацию об абоненте в следующем формате:

<фамилия> <имя> <отчество> (<улица> <дом>-<квартира>)

Пример ввода

5 3

261498

Pupkin Vasiliy Vasilyevich

Lenina 24-16

921611

Smirnov Pavel Andreevich

Kopylova 10-106

559173

Ivanova Marina Alexandrovna

Kalinina 120-51

267114

Sidorov Dmitriy Evgenyevich

Mira 22-14

861730

Petrova Anna Ivanovna

Totmina 9-3

261498

559173

861730

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

Pupkin Vasiliy Vasilyevich (Lenina 24-16)

Ivanova Marina Alexandrovna (Kalinina 120-51)

Petrova Anna Ivanovna (Totmina 9-3)

Данные будем хранить в массиве структур, который

отсортируем с учётом разрядов телефонных номеров, а ответ на

запрос будем искать бинарным поиском.

Page 80: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

80

1 #include<stdio.h>

2 struct ab{

3 int T;int t[6];char f[50];char a[50];};

4 void RadixMSD(ab a[],int n,int j){

5 int c[10],d[10],i;ab b[n];

6 for(i=0;i<10;++i)d[i]=0;

7 for(i=0;i<n;++i)d[(a[i].t[j])%10]++;

8 for(i=0;i<10;++i)c[i]=d[i];

9 for(i=1;i<10;++i)c[i]+=c[i-1];

10 for(i=n-1;i>=0;--i){

11 b[--c[(a[i].t[j])%10]]=a[i];}

12 for(i=0;i<n;++i)a[i]=b[i];

13 j++;

14 if(j<6)for(i=0;i<10;++i)

15 RadixMSD(a+c[i],d[i],j); }

16 main(){int i,j,k,m,n,l,r;

17 scanf("%d%d",&n,&m); ab a[n];

18 for(i=0;i<n;++i){

19 scanf("%d\n",&a[i].T);

20 a[i].t[0]=a[i].T;

21 for(j=5;j>0;--j){

22 a[i].t[j]=a[i].t[0]%10;

23 a[i].t[0]/=10;}

24 gets(a[i].f);gets(a[i].a);}

25 RadixMSD(a,n,0);

26 for(j=0;j<m;++j){

27 scanf("%d",&k);

28 l=0;r=n;

29 do{i=(l+r)/2;

30 if(a[i].T>k)r=i;else l=i;

31 }while(a[i].T!=k);

32 printf("%s (%s)\n",a[i].f,a[i].a);}}

Page 81: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

81

7. ДВУМЕРНЫЕ МАССИВЫ

7.1. ПРЕОБРАЗОВАНИЯ МАТРИЦ

Сайт acmp, «Курсы/Язык программирования С++/ Двумерные

массивы»

Тема «Базовые операции». Задачи A..G

Задача А. Двумерный массив (1232)

Задан целочисленный двумерный массив, состоящий из N строк и

M столбцов. Требуется вычислить сумму элементов в каждой

строке и в каждом столбце.

Входные данные. Первая строка содержит два натуральных числа

N и M – количество строк и столбцов двумерного массива. В

каждой из последующих N строк записаны M целых чисел –

элементы массива. Все числа во входных данных не превышают

100 по абсолютной величине.

Выходные данные. В первой строке выведите N чисел – суммы

элементов массива для каждой строки в отдельности. Во второй

строке в аналогичном формате выведите M чисел – суммы

элементов для каждого столбца. Третья строка должна быть

пустой, а далее должны следовать N строк по M чисел – исходный

массив, определенный во входных данных.

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

3 4 22 15 18

5 9 2 6 12 13 14 16

6 2 4 3

1 2 8 7 5 9 2 6

6 2 4 3

1 2 8 7

Для упрощения описания многочисленных циклов введём для них

макроопределение FOR(i,e), заменяемое препроцессором на

for(i=0;i<e;++i) с соответствующими заменами

Page 82: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

82

1 #include<iostream>

2 using namespace std;

3 #define FOR(i,e) for(i=0;i<e;++i)

4 main(){

5 int n,m,i,j,s;

6 cin>>n>>m;

7 int a[n][m];

8 FOR(i,n) FOR(j,m) cin>>a[i][j];

9 FOR(i,n){ s=0;

10 FOR(j,m) s+=a[i][j];

11 cout<<s<<' '; }

12 cout<<endl;

13 FOR(j,m){ s=0;

14 FOR(i,n) s+=a[i][j];

15 cout<<s<<' '; }

16 cout<<endl;

17 FOR(i,n){ cout<<endl;

18 FOR(j,m)cout<<a[i][j]<<' '; } }

Задача В. Транспонирование-1 (1233)

Задана целочисленная квадратная матрица размером N x N.

Требуется транспонировать ее относительно главной диагонали.

Входные данные. Первая строка содержит натуральное число N –

количество строк и столбцов матрицы. В каждой из последующих

N строк записаны N целых чисел – элементы матрицы. Все числа

не превышают 100 по абсолютной величине.

Выходные данные. Выведите матрицу, полученную

транспонированием исходной матрицы относительно главной

диагонали.

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

5

3 4 9 1 2

8 2 0 5 1

4 7 4 8 7

7 1 3 3 8

5 6 3 7 0

3 8 4 7 5

4 2 7 1 6

9 0 4 3 3

1 5 8 3 7

2 1 7 8 0

Page 83: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

83

1 #include <iostream> 2 using namespace std; 3 #define FOR(i,e) for(i=0;i<e;++i)

4 main(){int n,i,j; 5 cin>>n;

6 int a[n][n]; 7 FOR(i,n) FOR(j,n) cin>>a[i][j]; 8 FOR(i,n-1) for(j=i+1;j<n;++j)

9 swap(a[i][j],a[j][i]); 10 FOR(i,n) {

11 FOR(j,n) cout<<a[i][j]<<' '; 12 cout<<endl;} }

В последующих задачах на транспонирование C, D, E

(1234, 1235, 1236) следует, используя это решение, изменить его,

внимательно корректируя параметры циклов и параметры вызова

функции обмена значениями swap.

Задача F. Сумма матриц (1237)

Заданы две целочисленные матрицы, каждая из которых состоит

из N строк и M столбцов. Требуется вычислить их сумму.

Входные данные. Первая строка содержит два натуральных числа

N и M – количество строк и столбцов каждой матрицы. Далее

следует описание двух матриц. Каждая матрица состоит из N строк

по M целых чисел. Матрицы отделены друг от друга пустой

строкой. Все числа во входных данных не превышают 100 по

абсолютной величине.

Выходные данные. Матрица, полученная в результате суммы

заданных матриц.

Page 84: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

84

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

3 4

4 -2 6 1

-1 7 -4 3

5 3 9 4

2 -3 2 7

5 1 -1 0

-2 3 -4 2

6 -5 8 8

4 8 -5 3

3 6 5 6

1 #include<iostream> 2 using namespace std; 3 #define FOR(i,e) for(i=0;i<e;++i)

4 main(){ 5 int n,m,i,j; 6 cin>>n>>m; 7 int a[n][m],b[n][m],c[n][m]; 8 FOR(i,n) FOR(j,m) cin>>a[i][j]; 9 FOR(i,n){

10 FOR(j,m) { cin>>b[i][j]; 11 c[i][j]=a[i][j]+b[i][j]; 12 cout<<c[i][j]<<' ';} 13 cout<<endl;} }

Задача G. Произведение матриц (1238)

Заданы две целочисленные матрицы A и B. Матрица A состоит из

N строк и M столбцов, Матрица B состоит из M строк и P столбцов.

Требуется вычислить произведение данных матриц A*B.

Входные данные. Первая строка содержит три натуральных числа

N, M и P. Далее следует описание матриц A и B. Матрица A

состоит из N строк по M целых чисел. Матрица B состоит из M

строк по P чисел. Матрицы отделены друг от друга пустой

строкой. Все числа во входных данных не превышают 100 по

абсолютной величине.

Page 85: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

85

Выходные данные. Матрица, полученная в результате

произведения A*B.

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

2 2 3

2 3

-1 4

2 -3 4

3 1 0

13 -3 8

10 7 -4

1 #include<iostream> 2 using namespace std; 3 #define FOR(i,e) for(i=0;i<e;++i)

4 main(){ 5 int n,m,p,i,j,k; 6 cin>>n>>m>>p; 7 int a[n][m],b[m][p],c[n][p]; 8 FOR(i,n) FOR(j,m) cin>>a[i][j]; 9 FOR(j,m) FOR(k,p) cin>>b[j][k]; 10 FOR(i,n) FOR(k,p){

11 c[i][k]=0; 12 FOR(j,m) c[i][k]+=a[i][j]*b[j][k]; } 13 cout<<c[i][k]<<' ';} 14 cout<<endl;} }

Page 86: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

86

7.2. СИМВОЛЬНЫЕ МАТРИЦЫ

Сайт acmp, «Курсы/Язык программирования С++/

Символьные матрицы»

Тема «Символьные матрицы». Задачи A..F

Задача А. Симпатичный узор (924)

На днях Иван у себя в прихожей выложил кафель, состоящий из

квадратных черных и белых плиток. Прихожая Ивана имеет

квадратную форму 4х4, вмещающую 16 плиток. Теперь Иван

переживает, что узор из плиток, который у него получился, может

быть не симпатичным. С точки зрения дизайна симпатичным

узором считается тот, который не содержит в себе квадрата 2х2,

состоящего из плиток одного цвета.

По заданному расположению плиток в прихожей Ивана требуется

определить: является ли выполненный узор симпатичным.

Входные данные. 4 строки по 4 символа «W» или «B» в каждой,

описывающие узор из плиток. Символ «W» обозначает плитку

белого цвета, а «B» - черного.

Выходные данные. «Yes», если узор является симпатичным и

«No» в противном случае.

Примеры

№ Ввод Вывод 1 BWBW Yes

BBWB

WWBB

BWWW

2 BBWB No

BBWB

WWBW

BBWB

Page 87: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

87

1 #include<iostream>

2 using namespace std;

3 #define FOR(i,e) for(i=0;i<e;++i)

4 main(){

5 int i,j,k;string s[4];

6 FOR(i,4)cin>>s[i];

7 FOR(i,3)FOR(j,3){

8 k=(s[i][j]=='B')+(s[i+1][j+1]=='B')+

9 (s[i+1][j]=='B')+(s[i][j+1]=='B');

11 if(k==0||k==4){cout<<"No";return 0;} }

12 cout<<"Yes"; }

Задача C. Морской бой-2 (493)

«Морской бой» - игра для двух участников, в которой игроки по

очереди называют координаты на неизвестной им карте

соперника. Если у соперника по этим координатам имеется

корабль, то корабль или его часть «топится», а попавший получает

право сделать еще один ход. Цель игрока - первым поразить все

корабли противника. Но правила, по которым расставляются

корабли перед началом партии, несколько отличаются от

классических. Во-первых, игра происходит на поле размером N x

M, а не 10 x 10. Во-вторых, число кораблей, их размер и форма

выбираются игроками перед партией - так играть намного

интереснее.

Расставлены все свои корабли, кроме одного однопалубного.

Такой корабль занимает ровно одну клетку. Найдите число

способов поставить оставшийся однопалубный корабль. При этом

учитывайте, что по правилам его можно ставить только в ту

клетку, все соседние с которой не заняты. В этой задаче соседними

считаются клетки, имеющие общую сторону.

Входные данные. Первая строка содержит два числа: N и M (1 <=

N, M <= 100). Последующие N строк описывают игровое поле -

каждая из них содержит M символов. Символом «.» (точка)

обозначена свободная клетка, символом «*» (звездочка) - занятая

кораблем.

Выходные данные. Ответ на задачу.

Page 88: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

88

Примеры

№ Ввод Вывод 1 4 4 4

****

**..

*...

*...

2 4 3 0

***

...

...

***

Во избежание выхода за пределы игрового поля создадим

вокруг него рамку из точек и проверим все клетки внутри неё: 1 #include<iostream> 2 using namespace std; 3 #define FOR(i,e) for(i=0;i<e;++i) 4 main(){ 5 int n,m,i,j,k=0; 6 cin>>n>>m; 7 string s[n+2];s[0]="."; 8 FOR(i,m+1)s[0]+='.'; 9 s[n+1]=s[0]; 10 FOR(i,n+1){cin>>s[i];s[i]='.'+s[i]+'.';} 11 FOR(i,n+1)FOR(j,m+1)

12 if(s[i][j]=='.'&&

13 s[i-1][j]=='.'&&s[i+1][j]=='.'&

14 s[i][j-1]=='.'&&s[i][j+1]=='.')k++; 15 cout<<k; }

Решить задачи

B 715 Миша и негатив

D 926 Города-2

E 446 Табло

F 875 Игра «Жизнь»

Page 89: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

89

7.3. ЧИСЛОВЫЕ МАТРИЦЫ

Сайт acmp, раздел «Курсы/Язык программирования С++/

Целочисленные матрицы»

Тема «Целочисленные матрицы». Задачи A..J

Задача А. Сапер (234)

В "Сапер" (Minesweeper) играет один человек. Игра идет на

клетчатом поле (далее будем называть его картой) NxM (N строк,

M столбцов). В K клетках поля стоят мины, в остальных клетках

записано либо число от 1 до 8 — количество мин в соседних

клетках, либо ничего не написано, если в соседних клетках мин

нет. Клетки являются соседними, если они имеют хотя бы одну

общую точку, в одной клетке не может стоять более одной мины.

Изначально все клетки поля закрыты. Игрок за один ход может

открыть какую-нибудь клетку. Если в открытой им клетке

оказывается мина, он проигрывает, иначе игроку показывается

число, которое стоит в этой клетке, и игра продолжается. Цель

игры — открыть все клетки, в которых нет мин.

По заданным N, M, K и координатам мин восстановите полную

карту.

Входные данные. В первой строке содержатся числа N, M и K

(1<=N<=200, 1<=M<=200, 0<=K<=N*M). Далее идут K строк, в

каждой из которых содержится по два числа, задающих

координаты мин. Первое число в каждой строке задает номер

строки клетки, где находится мина, второе число — номер

столбца. Левая верхняя клетка поля имеет координаты (1,1),

правая нижняя — координаты (N,M).

Выходные данные. N строк по M символов — соответствующие

строки карты. j-й символ i-й строки должен содержать символ «*»

(звездочка) если в клетке (i,j) стоит мина, цифру от 1 до 8, если в

этой клетке стоит соответствующее число, либо «.» (точка), если

клетка (i,j) пустая.

Page 90: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

90

Пример ввода Пример вывода 10 9 23 .111..1*1

1 8 13*2..111

2 3 1**3.....

3 2 13*2.111.

3 3 .111.2*2.

4 3 233335*41

5 7 ********1

6 7 *6*7*8*41

7 1 13*4***2.

7 2 .1122321.

7 3

7 4

7 5

7 6

7 7

7 8

8 1

8 3

8 5

8 7

9 3

9 5

9 6

9 7

Page 91: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

91

1 #include<iostream> 2 using namespace std; 3 #define FOR(i,n) for(i=1;i<=n;++i) 4 main(){ 5 int n,m,i,j,k; 6 cin>>n>>m>>k; 7 string a[n+2];a[0]=""; 8 FOR(j,m+2)a[0]+="."; 9 FOR(i,n+1)a[i]=a[0]; 10 while(k){k--;cin>>i>>j;a[i][j]='*';} 11 FOR(i,n){ 12 FOR(j,m) 13 if(a[i][j]=='*')cout<<'*'; 14 else{ k= 15 (a[i-1][j-1]=='*')+(a[i-1][j]=='*')+ 16 (a[i-1][j+1]=='*')+(a[i][j-1]=='*')+ 17 (a[i][j+1]=='*')+(a[i+1][j-1]=='*')+ 18 (a[i+1][j]=='*')+(a[i+1][j+1]=='*'); 19 if(k)cout<<k;else cout<<'.';} 20 cout<<endl;}}

Задача B. Художник (27)

Известный художник решил написать новый шедевр. После

многих дней усердной работы он захотел исследовать свое

творение. Художник вспомнил, что картина писалась следующим

образом: сначала был взят белый холст, имеющий форму

прямоугольника шириной w и высотой h. Затем художник

нарисовал на этом холсте n прямоугольников со сторонами,

параллельными сторонам холста, и вершинами, расположенными

в целочисленных координатах. Помогите художнику определить

площадь незакрашенной части холста.

Входные данные. Первая строка содержит два натуральных числа

w и h (1 ≤ w, h ≤ 100). Во второй строке записано целое число n (0

≤ n ≤ 5000) – количество прямоугольников. Следующие n строк

содержат информацию о всех прямоугольниках. Каждая строка

описывает один прямоугольник в виде четырех чисел x1, y1, x2, y2

Page 92: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

92

где (x1, y1) и (x2, y2) – координаты левого верхнего и правого

нижнего угла прямоугольника соответственно.

Выходные данные. Одно целое число – площадь незакрашенной

части холста.

Примеры

№ Ввод Вывод

1 5 5 18

2

1 1 3 3

2 2 4 4

2 6 7 17

3

0 0 5 5

1 1 4 4

2 2 3 3

1 #include<iostream> 2 using namespace std; 3 #define FOR(i,b,e) for(i=b;i<e;++i) 4 main(){ 5 int w,h,i,j,n,x1,y1,x2,y2; 6 cin>>w>>h>>n; 7 int s=w*h; bool a[h][w]; 8 FOR(i,0,h)FOR(j,0,w)a[i][j]=true; 9 while(n){n--; 10 cin>>x1>>y1>>x2>>y2; 11 FOR(i,y1,y2)FOR(j,x1,x2) 12 if(a[i][j]){ a[i][j]=false;s--;}} 13 cout<<s;}

Задача D. Седловые точки (388)

Задана матрица, содержащая N строк и M столбцов. Седловой

точкой этой матрицы назовем элемент, который одновременно

является минимумом в своей строке и максимумом в своем

столбце. Найдите количество седловых точек заданной матрицы.

Page 93: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

93

Входные данные. В первой строке - целые числа N и M (1 <= N, M

<= 750). Далее следуют N строк по M чисел в каждой. Элементы

матрицы - целые числа, не превосходящие 1000 по абсолютной

величине. Числа могут быть разделены несколькими пробелами.

Выходные данные. Ответ на задачу.

Примеры

№ Ввод Вывод

1 2 2 4

0 0

0 0

2 2 2 1

1 2

3 4

Заведём массивы минимумов по строкам b и максимумов по

столбцам с. Учитывая солидные размеры матрицы, чтобы

сэкономить время при вводе вместо потоков, используем функции

форматного ввода-вывода из классического С.

1 #include<stdio.h>

2 using namespace std;

3 #define FOR(i,e) for(i=0;i<e;++i) 4 main(){

5 int n,m,i,j,s=0;

6 scanf("%d%d",&n,&m);

7 int a[n][m],b[n],c[m];

8 FOR(i,n)FOR(j,m)scanf("%d",&a[i][j]);

9 FOR(i,n){ b[i]=a[i][0];

10 FOR(j,m) if(a[i][j]<b[i]) b[i]=a[i][j];}

11 FOR(j,m){ c[j]=a[0][j];

12 FOR(i,n) if(a[i][j]>c[j]) c[j]=a[i][j];}

13 FOR(i,n)FOR(j,m)

14 if(a[i][j]==b[i]&&a[i][j]==c[j]) s++;

15 printf("%d",s); }

Page 94: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

94

Решить задачи

C 58 Проверка на симпатичность

E 54 Теория игр

F 88 Судоку

G 196 Спираль

H 197 Змейка

I 96 Винни-Пух

J 802 Магический квадрат

Page 95: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

95

8. ФАЙЛЫ

8.1. ФАЙЛОВЫЙ ВВОД И ВЫВОД

Уже в последних задачах мы столкнулись с необходимостью

вводить при отладке и проверке несколько строк входных данных,

возможно, несколько раз повторяя одни и те же действия. Дальше

эти объёмы будут больше.

Самое простое в такой ситуации – скопировать входные

данные из условия задачи в буфер и, запустив программу, навести

курсор на верхнее поле открывшегося окна консоли, кликнув

правой кнопкой мыши, выбрать «Изменить/Вставить».

Но это не всегда удобно. Например, мы можем захотеть

поэкспериментировать с разными другими наборами входных

данных. Пора этот процесс автоматизировать, вводя данные из

файла, как это делает проверяющая система.

Для этого создадим в любом текстовом редакторе, например

в уже привычной IDE, текстовый файл с входными данными

(скопировав их со страницы с условием задачи в браузере) и

сохраним его в той же папке, что и коды программы, под именем

input.txt. Будьте внимательны, многие системы по умолчанию

могут добавить расширение .txt. Поэтому убедитесь, что

получился файл с именем input.txt, а не input.txt.txt, и не просто

input.

В текст функции main() до первого оператора ввода вставим

строку:

freopen(”input.txt”,”r”,stdin); ,

означающую, что стандартный ввод (чтение) будет производится

из указанного файла, а не с консоли (клавиатуры).

Аналогично при необходимости можно добавить строку

переключения стандартного вывода (записи) в файл вместо

консоли (экрана):

freopen(”output.txt”,”w”,stdout); .

Page 96: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

96

Отметим, что в некоторых задачах могут встретиться

настолько объёмные тесты, что привычный и удобный потоковый

ввод/вывод через консольные потоки cin и cout из библиотеки

iostream при очень больших количествах обращений к ним займёт

неприемлемо много времени. В таких случаях следует вспомнить

и грамотно применить функции форматного ввода/вывода

классического языка С – scanf и printf из библиотеки stdio.h (но не

cstdio!), обычно работающие на порядок быстрее.

Page 97: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

97

8.2. СОРТИРОВКИ ФАЙЛОВ

Сгенерировать достаточно длинный файл чисел и

отсортировать его в соответствии с алгоритмами внешней

сортировки из курса информатики.

Для контроля добавим средство промежуточной печати

сортируемых частей файла.

Задача 1. Внешняя сортировка прямым слиянием

1 #include<iostream>

2 #include<fstream>

3 #define DEBUG

4 using namespace std;

5 #ifdef DEBUG

6 void prf(string fn){

7 ifstream F;int x; F.open(fn);

8 while(F>>x)cout<<x<<' ';cout<<endl;

9 F.close();}

10 #endif

11 main(){

12 int L0,L1,L2,N=1,n1,n2,a,b;bool z;

13 ifstream F0,F1,F2;ofstream f0,f1,f2;

14 #ifdef DEBUG // создание файла

15 f0.open("f0.txt");

16 do{a=rand()%200; f0<<a<<' ';}while(a);

17 f0.close();

18 #endif

19 do{ // начало основного цикла

20 F0.open("f0.txt");

21 f1.open("f1.txt");f2.open("f2.txt");

22 z=true;L1=0;L2=0;n1=N;

23 while(F0>>a){ // цикл разбиения

24 if(z){f1<<a<<' ';L1++;}

25 else {f2<<a<<' ';L2++;}

26 n1--; if(n1==0){z=!z;n1=N;}}

27 F0.close();f1.close();f2.close();

Page 98: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

98

28 #ifdef DEBUG

29 prf("f0.txt");cout<<N<<endl;

30 prf("f1.txt");prf("f2.txt");

31 #endif

32 f0.open("f0.txt");

33 F1.open("f1.txt");F2.open("f2.txt");

34 L0=L1+L2; // начало цикла слияния

35 do{

36 n1=N;n2=N;F1>>a;F2>>b;

37 do{

38 if(a<b){f0<<a<<' ';n1--;L1--;

39 if(L1*n1)F1>>a;

40 else {f0<<b<<' ';n2--;L2--;}}

41 else {f0<<b<<' ';n2--;L2--;

42 if(L2*n2)F2>>b;

43 else {f0<<a<<' ';n1--;L1--;}}

44 }while(n1*n2*L1*L2);

45 while(n1*L1){

46 F1>>a;f0<<a<<' ';n1--;L1--;}

47 while(n2*L2)

48 {F2>>b;f0<<b<<' ';n2--;L2--;}

49 }while(L1*L2); // конец цикла слияния

50 while(L1){F1>>a;f0<<a<<' ';L1--;}

51 while(L2){F2>>a;f0<<a<<' ';L2--;}

52 f0.close();F1.close();F2.close();

53 N*=2;

54 }while(N<L0); // конец основного цикла

55 #ifdef DEBUG

56 prf("f0.txt");

57 #endif

58 }

Page 99: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

99

Задача 2. Внешняя сортировка естественная

1 #include<iostream>

2 #include<fstream>

3 #define DEBUG

4 using namespace std;

5 #ifdef DEBUG

6 void prf(string fn){

7 ifstream F;int x; F.open(fn);

8 while(F>>x)cout<<x<<' ';cout<<endl;

9 F.close();}

10 #endif

11 main(){

12 int L1,L2,a,b,A,B;bool z;

13 ifstream F0,F1,F2;ofstream f0,f1,f2;

14 #ifdef DEBUG

15 f0.open("f0.txt");

16 do{a=rand()%200; f0<<a<<' ';}while(a);

17 f0.close();

18 #endif

19 do{ // начало основного цикла

20 F0.open("f0.txt");

21 f1.open("f1.txt");f2.open("f2.txt");

22 z=true;L1=0;L2=0;F0>>A;f1<<A<<' ';L1++;

23 while(F0>>a){if(a<A)z=!z; A=a;

24 if(z){f1<<a<<' ';L1++;} // цикл

25 else{f2<<a<<' ';L2++;}} // разбиения

26 F0.close();f1.close();f2.close();

27 if(L2==0)break; // выход из основного

28 #ifdef DEBUG // цикла

29 prf("f0.txt");prf("f1.txt");prf("f2.txt");

30 #endif

Page 100: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

100

31 f0.open("f0.txt");

32 F1.open("f1.txt");F2.open("f2.txt");

33 F1>>a;F2>>b;

34 do{ // начало цикла слияния

35 if(a<b){f0<<a<<' ';L1--;

36 if(L1){A=a;F1>>a;

37 if(a<A)do{

38 f0<<b<<' ';L2--;

39 if(L2){B=b;F2>>b;}

40 }while(L2&&b>=B);

41 if(L2==0)f0<<a<<' ';}

42 else{f0<<b<<' ';

43 while(F2>>b)f0<<b<<' ';}}

44 else{f0<<b<<' ';L2--;

45 if(L2){B=b;F2>>b;

46 if(b<B)do{

47 f0<<a<<' ';L1--;

48 if(L1){A=a;F1>>a;}

49 }while(L1&&a>=A);

50 if(L1==0)f0<<b<<' ';}

51 else{f0<<a<<' ';

52 while(F1>>a)f0<<a<<' ';}}

53 }while(L1*L2); // конец цикла слияния

54 while(F1>>a)f0<<a<<' ';

55 while(F2>>b)f0<<b<<' ';

56 f0.close();F1.close();F2.close();

57 }while(1); // конец основного цикла

58 #ifdef DEBUG

59 prf("f0.txt");

60 #endif

61 }

Page 101: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

101

8.3. ОБРАБОТКА ФАЙЛОВ

Задачи на работу с файлами будем проверять сами, при этом

сами будем создавать для этого файлы с входными данными.

Достаточно полные решения задач 3..6 могут позволить авторам

решений претендовать на автоматическое получение зачётов и

бонусы на экзаменах.

Задача 1. Чёт-нечет

Текстовый файл input.txt содержит натуральные числа,

разделённые пробелами. Записать нечётные числа в файл odd.txt,

а нечётные – в even.txt.

Сначала сгенерируем исходный файл, записывая в него

остатки от деления случайных целых чисел на 1000 до тех пор,

пока не встретится 0.

Затем составим массив потоков файлов записи из 2 элементов

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

исходного файла числа как индекс для выбора из массива файла,

куда это число писать. Читаем из исходного файла до тех пор, пока

он не кончится.

1 #include<fstream>

2 using namespace std;

3 main(){

4 int a;

5 ofstream ff("input.txt");

6 do{a=rand()%1000; ff<<a<<' ';}while(a);

7 ff.close();

8 ifstream in("input.txt");

9 ofstream out[2];

10 out[0].open("even.txt");

11 out[1].open("odd.txt");

12 while(in>>a)out[a%2]<<a<<' '; }

Page 102: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

102

Задача 2. Первокурсники всех групп, соединяйтесь!

Текстовые файлы mk101.txt, mn101.txt, mp101.txt, mp102.txt и

mt101.txt содержат упорядоченные по алфавиту списки

первокурсников по группам с указанием фамилии, имени,

отчества. Создать общий упорядоченный по алфавиту список

первокурсников с указанием групп.

Пример файла с общим списком:

Брин Сергей Михайлович МТ-101

Вентцель Елена Сергеевна МП-102

Демидович Борис Павлович МП-101

Дуров Павел Валерьевич МТ-101

Ильин Арлен Михайлович МН-101

Рошал Евгений Лазаревич МК-101

Стратегия слияния будет такой: к файлу-накопителю будем

по одному добавлять файлы, на ходу определяя, какую из двух

записей, считанных из двух сливаемых файлов, следует

записывать. Тактика слияния двух файлов будет такой: на каждом

шаге мы будем находиться в одном из состояний:

1) оба файла чтения кончились – закрыть все файлы;

2) один из файлов чтения кончился – читая до конца оставшийся

файл чтения, дописать файл записи;

3) есть незаписанный элемент одного из файлов чтения,

незаписанного элемента из другого файла чтения нет –

прочитать элемент из другого файла чтения;

4) есть два незаписанных элемента из файлов чтения – сравнить их

и записать меньший в файл записи.

Для индикации наличия прочитанных незаписанных

элементов и достижения концов файлов введём логические

переменные – флаги.

Page 103: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

103

1 #include<fstream>

2 using namespace std;

3 main(){

4 ifstream f0,f1; ofstream ff;

5 bool b0,b1,e0,e1;

6 string s0,s1,g[5]={"MK-101","MH-101",

"МП-101","МП-102","МТ-101"},

7 f[5]={"mk101.txt","mn101.txt",

"mp101.txt","mp102.txt","mt101.txt"};

8 for(int i=0;i<5;++i){

9 f0.open("m1.txt");ff.open("m0.txt");

10 while(getline(f0,s0))ff<<s0<<endl;

11 f0.close();ff.close();

12 f0.open("m0.txt");f1.open(f[i]);

13 ff.open("m1.txt");

14 e0=true;e1=true; // флаги концов файлов

15 b0=true;b1=true; // флаги использования

записей

16 while(e0||e1){

17 if(b0)if(e0&&getline(f0,s0))b0=false;

18 else e0=false;

19 if(b1)if(e1&&getline(f1,s1))b1=false;

20 else e1=false;

21 if(b0^b1)

22 if(b0){

23 if(s1.size()>0)

24 ff<<s1<<' '<<g[i]<<' '<<endl;

25 b1=true;}

26 else {ff<<s0<<endl;b0=true;}

27 else

28 if(s0<s1){ff<<s0<<endl;b0=true;}

29 else{if(s1.size()>0)

30 ff<<s1<<' '<<g[i]<<' '<<endl;

31 b1=true;} }

32 f0.close();f1.close();ff.close(); } }

В строках 23 и 29 делаем дополнительную проверку во

избежание записи пустых строк.

Page 104: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

104

Задача 3. Мальчики – налево, девочки – направо

Создать отдельные файлы списков мужчин и женщин, учитывая,

что отчество кончается на «ич» или «на».

Задача 3+. Создать файлы с мужскими и женскими именами без

повторов.

Задача 3++. Создать файлы с мужскими и женскими именами и со

счётчиками имён.

Задача 4. Куратор

Составить интерактивную программу поиска в общем списке

студентов по какому-нибудь признаку.

Задача 4+. Деканат

Составить интерактивную программу внесения изменений в

общем списке студентов.

Задача 5. Белый танец

На вечере посвящения в студенты присутствовали все

первокурсники в соответствии с общим списком, девушек

традиционно было меньше, чем юношей. Был объявлен белый

танец с условием, что все девушки приглашают юношей не из

своих групп. Предложить один из возможных списков пар.

Задача 6. Приёмная комиссия

В списке приёмной комиссии у некоторых студентов оказались

пропущены отчества. Обнаружить эти записи и высказать

предположения о том, юноша это или девушка. Составить для

этого списки заведомо мужских и женских имён. Учитывать

окончания фамилий и имён. Учитывать, что название группы

содержит '-' во 2-й (с 0) позиции, а отчество кончается на «ич»

или «на».

Page 105: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

105

9. РЕКУРСИЯ

Сайт acmp, раздел «Курсы/Язык программирования С++/

Рекурсия»

Тема «Рекурсия-1». Задачи A..D

Задача А. Разворот (149)

Дано натуральное число N и последовательность из N элементов.

Требуется вывести эту последовательность в обратном порядке.

Входные данные. В первой строке - натуральное число N (N ≤

1000). Во второй строке через пробел идут N целых чисел, по

модулю не превосходящих 1000 - элементы последовательности.

Выходные данные. Выведите заданную последовательность в

обратном порядке.

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

3 3 2 1

1 2 3

Мы уже решали эту задачу итерационным способом в разделе

«Массивы+». Для удобства сделаем массив глобальным и

построим рекурсивную функцию, печатающую элемент массива с

указанным номером и, если этот номер больше 0, вызывающую

себя с номером на 1 меньшим:

1 #include<iostream>

2 using namespace std;

3 int a[100000],n;

4 void Pr(int k){

5 cout<<a[k]<<' ';

6 if(k)pr(k-1); }

7 main(){

8 cin>>n;

9 for(int i=0;i<n;++i)cin>>a[i];

10 Pr(n-1);}

При изучении соответствующего раздела сделать эту же

задачу через стек.

Page 106: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

106

Задача В. Числа Фибоначчи (147)

Последовательностью Фибоначчи называется последовательность

чисел a0, a1, ..., an, ..., где a0 = 0, a1 = 1, ak = ak-1 + ak-2 (k > 1). Найти

N-е число Фибоначчи.

Входные данные. Вводится целое число N (0 ≤ N ≤ 30).

Выходные данные. Вывести N-е число Фибоначчи.

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

7 13

Эту задачу мы тоже уже решали итерационно в разделе

«Цикл с предусловием». Здесь надо написать рекурсивную

функцию от целого аргумента F(k), возвращающую k при k<2 и

F(k-1)+F(k-2) при k>1.

1 #include<iostream>

2 using namespace std;

3 int fib(int k){

4 if(k>1)return fib(k-2)+fib(k-1);

5 return k;}

6 main(){

7 int n;

8 cin>>n;

9 cout<<fib(n);}

При n<=30 эта программа даёт верные результаты за

приемлемое время, но при бóльших значениях начинает

«тормозить». Видно, что в 5-й строке фактически многократно

организуются одни и те же вычисления. Их результаты можно и

нужно запоминать для последующего использования. Расширим

разрядную сетку для наших чисел и будем возвращать не только

k-е значение ряда Фибоначчи, но и предыдущее (k-1)-е.

Page 107: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

107

1 #include<iostream>

2 using namespace std;

3 long long fib(int k,long long &g){

4 long long h;

5 if(k>1){g=fib(k-1,h);return g+h;}

6 else{g=0;return k;}}

7 main(){

8 int n;long long m;

9 cin>>n;

10 cout<<fib(n,m);}

Оцените быстродействие этого варианта и выясните, для

каких максимальных значений n он пригоден.

Задача С. Перестановки (350)

Дана строка, состоящая из N попарно различных символов.

Требуется вывести все перестановки символов данной строки.

Входные данные. Строку, состоящую не более чем из 8 символов,

символы - буквы английского алфавита и цифры.

Выходные данные. Выведите в каждой строке по одной

перестановке. Перестановки можно выводить в любом порядке.

Повторений и строк, не являющихся перестановками исходной,

быть не должно.

Примеры

№ Ввод Вывод

1 AB AB

BA

2 IOX XOI

OXI

XIO

IXO

OIX

IOX

Page 108: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

108

Из перерабатываемой строки последовательно удаляем по

одному символу, добавляя удалённый символ к строке-

накопителю, а с оставшейся строкой делаем то же самое, и так до

тех пор, пока оставшаяся строка не опустеет:

1 #include <iostream>

2 using namespace std;

3 void f(string s,string r){

4 int i;string t;

5 if(s.size())

6 for(i=0;i<s.size();i++){

7 t=s; f(t.erase(i, 1),r+s[i]); }

8 else cout<<r<<endl; }

9 main(){

10 string s;

11 cin>>s;

12 f(s,""); }

Эту задачу можно решить и по-другому, используя функцию

сортировки sort и функцию получения очередной перестановки

next_permutation из раздела algorithm стандартной библиотеки

шаблонов STL.

Указания к решению задачи D. Функция-2 (906)

Для экономии времени надо хранить все однажды вычисленные

значения в трехмерном массиве, не вычисляя их повторно.

Тема «Рекурсия-2». Задача А. Лесенка (16)

Лесенкой называется набор кубиков, в котором каждый более

верхний слой содержит кубиков меньше, чем предыдущий.

Требуется написать программу, вычисляющую число лесенок,

которое можно построить из N кубиков.

Входные данные. Натуральное число N (1 ≤ N ≤ 100) – количество

кубиков в лесенке.

Выходные данные. Число лесенок, которые можно построить из N

кубиков.

Page 109: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

109

Примеры

№ Ввод Вывод

1 3 2

2 6 4

1 #include <iostream>

2 using namespace std;

3 int r=0;

4 void F(int k,int m) {

5 if(k==0)r++;

6 else while(m<k){m++; F(k-m,m);} }

7 main() {

8 int n;

9 cin>>n;

10 F(n,0);

11 cout<<r; }

Тема «Функция-1». Задача С. Число сочетаний (1227)

Сайт ipc/Учебные задачи/Алгоритмы и структуры данных

Задача 2288. Число сочетаний

Напишите рекурсивную функцию нахождения числа сочетаний из

N по K. Вместо факториальной формулы (с. 50) воспользуйтесь

следующими рекуррентными соотношениями:

1

11

0,1

K

N

K

N

K

N

N

NN CCCCC

Задача 2289. Степень числа

Напишите рекурсивную функцию нахождения xn для целых n без

использования функции pow и n-кратного умножения.

Воспользуйтесь следующими соотношениями:

x0=1,

xn=(xn/2)2 при чётных n>0,

xn=x xn-1 при нечётных n>0,

xn=1/x–n при n<0.

Page 110: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

110

Задача Крамера. Определитель матрицы и решение системы

линейных уравнений

Составить рекурсивную функцию вычисления определителя

матрицы и решить с её помощью систему из N линейных

уравнений с N неизвестными. Такую систему можно представить

как произведение матрицы А на вектор переменных Х, в

результате чего получается вектор правых частей В.

Вводится целое число N, затем N строк по N разделённых

пробелами чисел, элементов матрицы коэффициентов системы

уравнений, затем строка из N чисел – столбец правых частей.

Напечатать строку из N чисел – решение системы.

Пример ввода 1:

2

1 2

3 4

5 6

Пример вывода 1:

-4 4.5

Пример ввода 2:

10

1 1 1 1 1 1 1 1 1 1

1 2 1 1 1 1 1 1 1 1

1 1 3 1 1 1 1 1 1 1

1 1 1 4 1 1 1 1 1 1

1 1 1 1 5 1 1 1 1 1

1 1 1 1 1 6 1 1 1 1

1 1 1 1 1 1 7 1 1 1

1 1 1 1 1 1 1 8 1 1

1 1 1 1 1 1 1 1 9 1

1 1 1 1 1 1 1 1 1 10

55 57 61 67 75 85 97 111 127 145

Пример вывода 2:

1 2 3 4 5 6 7 8 9 10

Для вычисления определителя используем стандартный

метод разложения в сумму по первой строке. Для того чтобы

матрицы, хранимые в двумерных массивах, передавать в функцию

Page 111: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

111

вычисления определителя, воспользуемся указателями, заодно

опишем через указатели и все одномерные массивы. Между

прочим, такую программу можно будет компилировать даже в IDE

MS Visual Studio. 1 #include<iostream>

2 using namespace std;

3 typedef double *pd;

4 #define FOR(i,b,e) for(i=b;i<e;++i)

5 double det(double **a,int n){

6 if(n==1)return a[0][0];

7 int i,j,k,z=-1; double d=0,**c=new pd[n-1];

8 c[0]=new double[(n-1)*(n-1)];

9 FOR(i,1,n-1)c[i]=c[i-1]+n-1;

10 FOR(k,0,n){ z=-z;

11 FOR(i,0,n-1)FOR(j,0,n-1)

12 c[i][j]=(j<k)?a[i+1][j]:a[i+1][j+1];

13 d+=z*a[0][k]*det(c,n-1);}

14 delete c[0];delete c;

15 return d;}

16 int main(){

17 freopen("input.txt","r",stdin);

18 int n,i,j,k; cin>>n;

19 double **a=new pd[n],*b=new double[n],

20 d,**c=new pd[n],*x=new double[n];

21 a[0]=new double[n*n];c[0]=new double[n*n];

22 FOR(i,1,n){ a[i]=a[i-1]+n; c[i]=c[i-1]+n;}

23 FOR(i,0,n)FOR(j,0,n)cin>>a[i][j];

24 FOR(i,0,n)cin>>b[i];

25 d=det(a,n);

26 if(d)FOR(k,0,n){

27 FOR(i,0,n)FOR(j,0,n)

28 c[i][j]=(j==k)?b[i]:a[i][j];

29 x[k]=det(c,n)/d; cout<<x[k]<<' ';}

30 else cout<<”No”;

31 return 0;}

На практике программы с одномерными массивами

эффективнее оптимизируются и лучше используют кэш

Page 112: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

112

процессора, чем подобные программы с двумерными массивами,

поэтому пару индексов i,j в матрице n×n преобразуем в индекс

i*n+j в соответствующем одномерном массиве длиной n*n. Но

этот вариант можно компилировать только компилятором GNU

C++, т.к. такие динамические массивы относятся пока к

нестандартным расширениям языка. 1 #include<iostream>

2 using namespace std;

3 #define FOR(i,b,e) for(i=b;i<e;++i)

3 double det(double a[],int n){

4 if(n==1)return a[0];

5 int i,j,k,z=-1; double d=0,c[(n-1)*(n-1)];

6 FOR(k,0,n){ z=-z;

7 FOR(i,0,n-1)FOR(j,0,n-1)

8 c[i*(n-1)+j]=

9 (j<k)?a[(i+1)*n+j]:a[(i+1)*n+j+1];

10 d+=z*a[k]*det(c,n-1);}

11 return d;}

12 main(){

13 freopen("input.txt","r",stdin);

14 int n,i,j,k; cin>>n;

15 double a[n*n],b[n],x[n],c[n*n],d;

16 FOR(i,0,n)FOR(j,0,n)cin>>a[i*n+j];

17 FOR(i,0,n)cin>>b[i];

18 d=det(a,n);

19 if(d)FOR(k,0,n){

20 FOR(i,0,n)FOR(j,0,n)

21 c[i*n+j]=(j==k)?b[i]:a[i*n+j];

22 x[k]=det(c,n)/d; cout<<x[k]<<' ';}

23 else cout<<”No”;}

Сравните время работы двух вариантов программы на одних

и тех же входных данных. Видно, что во втором варианте

программы динамические массивы в часто вызываемой

рекурсивной функции, создаваемые и удаляемые в системном

стеке, обрабатываются быстрее, чем такие же массивы, под

которые в первом варианте выделялась и освобождалась

оперативная память через указатели.

Page 113: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

113

10. СТРУКТУРЫ ДАННЫХ И АЛГОРИТМЫ ИЗ

СТАНДАРТНОЙ БИБЛИОТЕКИ ШАБЛОНОВ STL

10.1. СТЕКИ

Сайт ipc. Модуль «Стек». Задача А. Наоборот (ipc-173)

Ввод содержит одну строку текста длиной не более 100 символов.

Вывести введенную строку в обратном порядке.

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

А роза упала на лапу Азора. .арозА упал ан алапу азор А 1 #include<iostream>

2 #include<stack>

3 using namespace std;

4 main(){ string t; stack<char>s;

5 getline(cin,t);

6 for(auto c:t)s.push(c);

7 while(!s.empty()){cout<<s.top();s.pop();}}

Задача B. Обработка последовательности символов 49 (ipc-510)

Дана строка, состоящая из английских слов, разделенных

пробелами (одним или несколькими). Вывести строку,

содержащую эти же слова, разделенные одним пробелом и

расположенные в обратном порядке.

Ввод. В первой строке находится исходная строка длинойБ=256.

Вывод. Вывести преобразованную строку.

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

This is a simple example example simple a is This 1 #include<iostream>

2 #include<stack>

3 using namespace std;

4 main(){

5 string t;stack<string>s;

6 while(cin>>t)s.push(t);

7 cout<<s.top();s.pop();

8 while(!s.empty()){

9 cout<<' '<<s.top();s.pop();} }

Page 114: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

114

Задача C. Скобки (ipc-39)

Определить, является ли правильной последовательность из N

круглых, квадратных и фигурных скобок, т.е. соответствует ли

каждой открывающей скобке закрывающая и правильно ли они

вложены.

Ввод. В первой строке находится число скобок N (1 ≤ N ≤ 100 000),

во второй – N символов из набора (, ), [, ], {, }.

Вывод. Выводится слово "Yes", если последовательность является

правильной, или "No", если нет.

Примеры

№ Ввод Вывод

1 6 No

([())]

2 24 Yes

{[()([]{})[]]({}{{}})}[]

1 #include<iostream>

2 #include<stack>

3 using namespace std;

4 int main(){

5 stack<char>s; int n; char c;

6 cin>>n;

7 for(;n>0;n--){

8 cin>>c;

9 if(c=='('||c=='['||c=='{')s.push(c);

10 else if(c==')'&&!s.empty()&&s.top()=='(')

11 s.pop();

12 else if(c==']'&&!s.empty()&&s.top()=='[')

13 s.pop();

14 else if(c=='}'&&!s.empty()&&s.top()=='{')

15 s.pop();

16 else n=-1;}

17 if(s.empty()&&n==0)cout<<"Yes";

18 else cout<<"No"; }

Page 115: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

115

Задача D. Скобки+ (ipc-650)

Определить, является ли правильной последовательность из

круглых, квадратных и фигурных скобок, т.е. соответствует ли

каждой открывающей скобке закрывающая и правильно ли они

вложены.

В первой строке находится одно целое число N (1 ≤ N ≤ 100) –

количество проверяемых последовательностей, далее следует N

непустых строк, состоящих из символов (, ), [, ], {, }, длиной до 100

символов.

Для каждой последовательности скобок вывести сообщение "Yes",

если последовательность является правильной, или "No", если нет.

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

3 Yes

([]) No

} No

[(]]

Задача E. Спичрайтер Йоды (ipc-2062)

Всем известно, что у каждого важного общественного деятеля есть

собственный спичрайтер, помогающий подготовить публичную

речь, сделать ее более выразительной и интересной. Глава Ордена

джедаев магистр Йода не исключение.

На первый взгляд может показаться, что спичрайтеру Йоды

приходится тяжелее других: все-таки речь магистра своеобразна и

ее изучение требует серьезных усилий. На самом деле все

несколько проще. Спичрайтеру Йоды достаточно сначала

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

порядок слов в каждом предложении на обратный. В силу того, что

алгоритм преобразования обычной речи в речь магистра Йоды

достаточно однообразен, спичрайтер решил автоматизировать

этот процесс и попросил вас написать программу, которая будет

преобразовывать речь, составленную им для обычного человека, в

речь для Йоды.

В единственной строке входного файла задана речь, составленная

спичрайтером. Речь состоит из предложений, отделенных друг от

Page 116: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

116

друга точками (точка ставится сразу после последнего слова в

предложении).

Каждое предложение состоит из слов. Предложение содержит по

крайней мере одно слово. Соседние слова разделены ровно одним

пробелом. Слово – непустая последовательность строчных

латинских букв. Строка не содержит лишних пробелов.

Гарантируется, что строка не пуста и ее длина не превосходит

20000 символов.

В одной строке выведите преобразованную для Йоды речь в

соответствии с форматом входных данных. Следует строго

соблюдать формат вывода речи, описанный во входных данных.

Пример ввода

you should solve this problem. its easy.

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

problem this solve should you. easy its.

Задача F. Разворот (acmp-149)

Дано натуральное число N и последовательность из N элементов.

Требуется вывести эту последовательность в обратном порядке.

Входные данные. В первой строке - натуральное число N (N ≤

1000). Во второй строке через пробел идут N целых чисел, по

модулю не превосходящих 1000 - элементы последовательности.

Выходные данные. Выведите заданную последовательность в

обратном порядке.

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

3 3 2 1

1 2 3

Мы уже решали эту задачу итерационно (с. 60) и рекурсивно

(с. 105). Решить задачу через стек.

Page 117: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

117

Задача G. Измени порядок (acmp-1200)

На одном из предприятий установлена пропускная система,

которая ежедневно фиксирует порядок прихода сотрудников,

используя персональные магнитные карты. Директора

предприятия заинтересовал список сотрудников, регулярно

опаздывающих на работу, в целях последующего возможного их

сокращения. Для этого он сделал распечатку фамилий

сотрудников за последние K дней. Распечатка представляла собой

K строк текста, в каждой из которых были записаны сотрудники,

упорядоченные по времени прихода. Но такое представление

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

опоздавшие сотрудники. Разработать конвертор формата данных,

изменяющий порядок списков сотрудников.

Входные данные. Первая строка содержит натуральное число K (K

≤ 10) – число дней. Далее идут K строк, в каждой из которых задана

последовательность фамилий сотрудников, разделенных ровно

одним пробелом, в порядке их прихода на работу в один из K дней.

Общее число сотрудников на предприятии не превышает 100,

гарантируется, что каждый день на работу приходит хотя бы один

сотрудник. Фамилия сотрудника – последовательность символов

английского алфавита длиной от 1 до 100 символов.

Выходные данные. Выведите ровно K строк в формате, удобном

для отслеживания опаздывающих сотрудников.

Пример ввода

3

Ivanov Petrov Sidorov

Bistrov Shustrov Serednyakov Opozdalova

Kuznetsova Ostapenko

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

Sidorov Petrov Ivanov

Opozdalova Serednyakov Shustrov Bistrov

Ostapenko Kuznetsova

Эту задачу мы уже решали через строку-накопитель и через

строковый поток. Решите её через стек.

Page 118: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

118

Задача H. Обратная польская запись

Преобразовать строку, содержащую арифметическое выражение с

целыми числами в обычной (инфиксной) форме со скобками, в

обратную польскую (постфиксную) форму.

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

(2*5+4^2)/(3^3-14) 2 5 * 4 2 ^ + 3 3 ^ 14 - /

Входные данные поместим в строку s. Для построения

результата будем использовать строку r. В строке p соберём

символы операций, а в массиве k – их приоритеты на тех же

позициях, что позволит нам определять приоритеты операций.

Символы операций будем помещать в стек q. Операнды и

операции в выходной строке будем разделять пробелами.

1 #include<iostream>

2 #include<stack>

3 using namespace std;

4 main(){

5 string s,r="",p="(+-*/^";

6 int k[6]={0,1,1,2,2,3}; stack<char>q;

7 getline(cin,s);

8 for(auto e:s)if(e!=' ')

9 if(e>='0'&&e<='9')r+=e;

10 else{ r+=' ';

11 if(q.empty()||e=='(')q.push(e);

12 else if(e==')'){

13 while(q.top()!='('){

14 r+=q.top();r+=' ';q.pop();}

15 q.pop(); }

16 else{

17 while(!q.empty()&&

18 k[p.find(e)]<=k[p.find(q.top())]){

19 r+=q.top();r+=' ';q.pop(); }

20 q.push(e);}}

21 while(!q.empty()){

22 r+=' ';r+=q.top();q.pop();}

23 cout<<r;}

Page 119: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

119

Задача I. Стековый калькулятор

Вычислить значение целочисленного арифметического

выражения, заданного в постфиксной форме, где операнды и знаки

операций разделены пробелами.

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

2 5 * 4 2 ^ + 3 3 ^ 14 - / 2

Используем то, что операнды и операции разделены

пробелами, и превратим входную строку в строковый поток ввода.

Строки с операндами будем преобразовывать в целые числа с

помощью функции stoi.

1 #include<iostream>

2 #include<sstream>

3 #include<stack>

4 #include<cmath>

5 using namespace std;

6 main(){

7 string r,t,p="+-*/^";

8 int a,b; stack<int>v;

9 getline(cin,r);

10 stringstream ss(r);

11 while(ss>>t)

12 if(p.find(t)==-1)v.push(stoi(t));

13 else{

14 b=v.top();v.pop();

15 a=v.top();v.pop();

16 if(t=="+")v.push(a+b);

17 else if(t=="-")v.push(a-b);

18 else if(t=="*")v.push(a*b);

19 else if(t=="/")v.push(a/b);

20 else if(t=="^")v.push(pow(a,b));}

21 cout<<v.top();}

Page 120: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

120

Задача I. Умный калькулятор

Вычислить значение арифметического выражения, содержащего

скобки, знаки арифметических операций, целые числа и

десятичные дроби.

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

(6*5.5+4^2)/(3^3-13) 3.5

Указания. Используйте коды задач G и H. Для преобразования

строк в дробные числа можно использовать функцию stof.

Page 121: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

121

10.2. ВЕКТОРЫ

Обычно в векторах возникает необходимость, когда размер

массива заранее неизвестен или может изменяться. Но мы

посмотрим сначала работу с векторами на тех же задачах, где

можно использовать обычные массивы.

Сайт acmp, «Курсы/Язык программирования С++/

Сортировка»

Тема «Быстрая сортировка». Задача В. Арифметическая

прогрессия (475)

Задана последовательность натуральных чисел из диапазона [1,

2147483647]. Необходимо определить, можно ли выстроить эти

числа в отрезок арифметической прогрессии. При необходимости

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

Входные данные. Последовательность натуральных чисел.

Количество чисел в последовательности может быть от 2 до 100

000. Числа в файле разделены пробелами или символами перехода

на новую строку.

Выходные данные. «Yes» в случае положительного ответа либо

«No» в противоположном случае.

Примеры

№ Ввод Вывод

1 80 50 10 30 70 40 20 60 90 Yes

2 1 2 3 5 No

Понятно, что числа надо отсортировать и проверить на

одинаковую разность между соседями. Тонкостями сортировки

мы здесь заниматься не будем, а воспользуемся готовым

библиотечным алгоритмом.

Page 122: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

122

1 #include<iostream>

2 #include<vector>

3 #include<algorithm>

4 using namespace std;

5 main(){

6 freopen("input.txt","r",stdin);

7 int a,i; vector<int> b;

8 while(cin>>a)b.push_back(a);

9 if(b.size()>2){

10 sort(b.begin(),b.end());

11 a=b[1]-b[0];

12 for(i=2;i<b.size();++i)

13 if(b[i]-b[i-1]!=a){

14 cout<<"No";return 0; } }

15 cout<<"Yes";}

Сайт acmp, «Курсы/Язык программирования С++/ Двумерные

массивы»

Тема «Базовые операции». Задача А. Двумерный массив (1232)

Задан целочисленный двумерный массив, состоящий из N строк и

M столбцов. Требуется вычислить сумму элементов в каждой

строке и в каждом столбце.

Входные данные. Первая строка содержит два натуральных числа

N и M – количество строк и столбцов двумерного массива. В

каждой из последующих N строк записаны M целых чисел –

элементы массива. Все числа во входных данных не превышают

100 по абсолютной величине.

Выходные данные. В первой строке выведите N чисел – суммы

элементов массива для каждой строки в отдельности. Во второй

строке в аналогичном формате выведите M чисел – суммы

элементов для каждого столбца. Третья строка должна быть

пустой, а далее должны следовать N строк по M чисел – исходный

массив, определенный во входных данных.

Page 123: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

123

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

3 4 22 15 18

5 9 2 6 12 13 14 16

6 2 4 3

1 2 8 7 5 9 2 6

6 2 4 3

1 2 8 7

Мы уже решали эту задачу, сохраняя матрицу в двумерном

массиве. Здесь поработаем через векторы, используя, где это

уместно, перебор элементов контейнера.

1 #include<iostream>

2 #include<vector>

3 using namespace std;

4 main(){

5 freopen("input.txt","r",stdin);

6 int n,m,i,j,s;

7 cin>>n>>m;

8 vector<vector<int> >a(n,vector<int>(m));

9 for(i=0;i<n;++i)for(j=0;j<m;++j)

10 cin>>a[i][j];

10 for(auto b:a){s=0;

11 for(auto c:b)s+=c;

12 cout<<s<<' '; }

13 cout<<endl;

14 for(j=0;j<m;++j){s=0;

15 for(i=0;i<n;++i)s+=a[i][j];

16 cout<<s<<' '; }

17 cout<<endl<<endl;

18 for(auto b:a){

19 for(auto c:b)cout<<c<<' ';

20 cout<<endl;} }

Page 124: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

124

10.3. СПИСКИ

Сайт ipc. Модуль «Списки»

Задача А. Дефрагментация диска FAT16 (ipc-811)

Дисковое пространство поделено на так называемые кластеры.

При записи на диск файлы разделяются на части размером с

кластер. Если все части файла размещены последовательно в

последовательных кластерах диска, то последовательное чтение

файла происходит максимально быстро. При изменении файла

отдельные его части (фрагменты) могут оказаться разбросанными

по всему диску в произвольном порядке, т. е. файл становится

фрагментированным. При этом быстродействие компьютера

снижается. Обычно дефрагментация проводится, когда число

фрагментированных файлов составляет 10-20% или более от числа

всех файлов. Для определения степени фрагментации можно

использовать таблицу размещения файлов FAT (File Allocation

Table). Упрощенно ее можно описать следующим образом.

Дисковое пространство делится на M кластеров, нумерующихся с

1 до M. В таблице FAT для каждого кластера диска записывается

число 0, если соответствующий кластер свободен, или число −1,

если это последний кластер файла, или число от 1 до M,

указывающее на следующий кластер, занятый файлом.

В первой строке содержится количество кластеров на диске M (1

≤ M ≤ 10000), в последующих M строках – таблица FAT. Данные

корректны, т.е. не содержат циклов и пересечений.

В первой строке вывести общее число файлов на диске, во второй

строке – число фрагментированных файлов. Файл будем считать

не фрагментированным, если для всех частей файла верно, что i

часть файла занимает b+i−1 кластер, где b – первый кластер файла.

Page 125: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

125

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

5 2

3 1

0

-1

5

-1

Число файлов подсчитать легко – сколько раз встретится -1.

Сложнее отследить непрерывность последовательности. Это

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

сначала ещё при подсчёте кластеров с -1 будем помечать их в

векторе b. Затем двигаемся в направлении уменьшения номера

кластера, пока мы видим в предыдущем кластере номер

последующего, и останавливаемся справа от кластера с 0 или с -1,

значит, мы прошли нефрагментированный файл, иначе – мы

наткнулись на фрагмент другого файла. Уменьшая в нужных

случаях общий счётчик файлов, мы получим в остатке число

фрагментированных файлов. 1 #include<iostream>

2 #include<vector>

3 using namespace std;

4 main(){ int m,i,f=0;

5 cin>>m;

6 int a[m+1];vector<bool>b(m+1,true);

7 for(i=1;i<=m;++i){

8 cin>>a[i];

9 if(a[i]>=0)b[a[i]]=false;

10 else f++;}

11 cout<<f<<endl;

12 i=m;

13 do{

14 while(i&&a[i]!=-1)i--;

15 while(i&&a[i-1]==i)i--;

16 if(b[i])f--;

17 i--;} while(i>0);

18 cout<<f;}

Page 126: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

126

Задача В. Переключение между окнами (ipc-1025)

Когда пользователь работает в операционной системе Windows, у

него часто запущено несколько приложений. Каждое из

приложений работает в отдельном окне. Для переключения между

окнами используется комбинация клавиш Alt+Tab. Эта

комбинация делает активным окно, в котором пользователь

работал перед тем, как перейти в текущее активное окно.

Чтобы переключиться в другое окно, можно нажать клавишу Alt и

затем, не отпуская ее, несколько раз нажать клавишу Tab. Чтобы

понять, какое окно станет активным после этого, воспользуемся

следующей моделью. Пусть запущено n приложений. Приложения

в операционной системе организованы в виде списка и

упорядочены по убыванию времени последней активности. То

есть приложение, окно которого является активным в настоящий

момент, – первое в списке, приложение, окно которого было

активно перед этим, – второе и т. д.

Если нажать клавишу Alt и затем, не отпуская ее, нажать клавишу

Tab k раз, то активным станет окно приложения, которое

находится на (k mod n) + 1-м месте в списке. Здесь a mod b означает

остаток от деления a на b. Иными словами, операционная система

рассматривает список как циклический, переходя после

последнего элемента списка к первому.

При запуске нового приложения оно добавляется в начало списка.

Задана последовательность действий пользователя, где каждое

действие – либо запуск приложения, либо переключение между

окнами. Выведите в выходной файл, в каком порядке пользователь

работал с приложениями.

Ввод. Первая строка содержит целое число n – количество

действий пользователя (1 ≤ n ≤ 1000). Следующие n строк

содержат описание действий пользователя. Запуск приложения

описывается строкой "Run <имя приложения>". Здесь <имя

приложения> - строка из не более чем 100 латинских букв, цифр и

пробелов. Она отделена от слова "Run" ровно одним пробелом. Все

имена приложений различны. Большие и маленькие буквы

считаются различными. Переключение между приложениями

Page 127: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

127

описывается строкой "Alt+Tab+...+Tab", здесь подстрока "+Tab"

повторена в точности столько раз, сколько раз пользователь нажал

клавишу Tab, не отпуская клавишу Alt. Это количество не

превышает 100. Первая команда во входном файле – всегда

команда "Run".

Вывод. Вывести n строк – последовательность имен приложений,

с которыми работал пользователь в порядке, в котором их окна

становились активными.

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

6 Mozilla Firefox

Run Mozilla Firefox Free Pascal

Run Free Pascal Mozilla Firefox

Alt+Tab Miranda IM

Run Miranda IM Free Pascal

Alt+Tab+Tab Free Pascal

Alt+Tab+Tab+Tab

1 #include<iostream>

2 #include<list>

3 using namespace std;

4 int main(){

5 int n;list<string>d;string s;

6 cin>>n;getline(cin,s);

7 while(n){n--;

8 getline(cin,s);

9 if(s[0]=='R')d.push_front(s.erase(0,4));

10 else{ auto i=d.begin();

11 advance(i,((s.size())/4)%d.size());

12 d.push_front(*i);

13 d.erase(i); }

14 cout<<d.front()<<endl;} }

Объявляемая в 11-й строке переменная i – итератор

(указатель) в контейнере-списке d, указывающий сначала на

начало списка, а затем меняющийся в соответствии с количеством

«Tab».

Page 128: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

128

Задача С. Склад Оби-Вана Кеноби (ipc-2063)

Все мечи Оби-Вана Кеноби пронумерованы. Оби-Ван Кеноби

хранит все свои мечи на очень длинном столе. Когда он хочет

вооружиться, то он берет самый правый меч со стола, и идет по

своим делам. Оби-Ван Кеноби орудует взятым мечом, пока не

потеряет или не сломает его.

Иногда кто-нибудь дарит Оби-Вану Кеноби новый меч, и тогда он

просто кладет его на стол справа к тем, что уже лежат там. Но

самое страшное случается тогда, когда к столу подходит мама

Оби-Вана Кеноби. Мама всегда возмущается, что мечи лежат

неупорядоченно. Чтобы исправить это, она забирает всю левую

половину мечей (если мечей на столе было нечетное количество,

то мама забирает наибольшее целое число мечей, меньшее

половины их общего количества) и начинает их подкладывать

справа к оставшимся. Причем сначала она кладет меч, который

изначально был самым левым, потом правее от него кладет второй

меч и так далее. Изначально стол был пуст.

Определите, в каком порядке лежат мечи у Оби-Вану Кеноби на

данный момент. В первой строке дано натуральное числа n –

количество изменений, произошедших на столе (1 ≤ n ≤ 106). В

следующих n строках описаны изменения в следующем формате:

если строка начинается со слова add, то в той же строке через

пробел находится число x (1 ≤ x ≤ n) – личный номер меча,

подаренного Оби-Вану Кеноби. Гарантируется, что мечей с

таким номером Оби-Вану Кеноби раньше не дарили и больше

не подарят;

если строка содержит единственное слово take, то это означает,

что Оби-Ван Кеноби забрал самый правый меч со стола с собой;

если на столе не было мечей, то ничего не произошло;

если же строка содержит единственное слово mum!, то это

означает, что к столу подошла мама и навела порядок:

если на столе было меньше двух мечей, то ничего не произошло.

В первой строке выходного файла выведите число k – количество

мечей, лежащих на данный момент на столе у Оби-Вана Кеноби.

В следующей строке выведите k чисел через пробел – личные

Page 129: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

129

номера мечей, лежащих на столе, в том порядке, в котором они на

нем лежат (слева направо). Если k=0, то вторую строку не

выводить.

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

8 5

add 1 4 3 5 1 2

add 2

add 4

add 3

add 5

add 8

take

mum!

Будем хранить две половины перечня мечей в двух списках 1 #include<iostream>

2 #include<list>

3 using namespace std;

4 main(){

5 int n,k; list<int>c,d; string s;

6 cin>>n;

7 while(n){n--; cin>>s;

8 if(s=="add"){

9 cin>>k;

10 d.push_back(k);

11 if(d.size()-c.size()>1){

12 c.push_back(d.front());

13 d.pop_front(); } }

14 else if(s=="take"){

15 if(!d.empty())d.pop_back();}

16 else if(!c.empty())swap(c,d);

17 if(d.size()<c.size()){

18 d.push_front(c.back());

19 c.pop_back();}}

20 cout<<c.size()+d.size()<<endl;

21 for(auto e:c)cout<<e<<' ';

22 for(auto e:d)cout<<e<<' '; }

Page 130: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

130

10.4. ОЧЕРЕДИ

Сайт ipc. Задача Городской парад (ipc-1501)

Шеф Виггам должен обеспечить правильный порядок движения

платформ на городском параде. Платформы могут прибывать в

любом порядке, но должны выходить на центральную площадь

строго в порядке возрастания номеров. Виггам может направить

платформу либо сразу на площадь, либо сначала на боковую

улицу, а затем с нее на площадь. Длина боковой улицы достаточна

для размещения всех платформ, но ширина улиц не позволяет

одной платформе обгонять другую.

Напишите программу, определяющую, сможет ли Виггам

обеспечить правильный порядок движения платформ на параде.

Первая строка ввода содержит одно целое число N (1 ≤ N ≤ 100) –

количество платформ. Вторая строка содержит N различных

целых чисел от 1 до N – номера платформ в порядке прибытия.

Вывести сообщение "YES", если можно обеспечить правильный

порядок платформ, или сообщение "NO", если нельзя.

Примеры

№ Ввод Вывод

1 4 YES

1 3 4 2

2 4 NO

4 3 2 1

1 #include <iostream>

2 #include <queue>

3 using namespace std;

4 main(){

5 queue<int>q;

6 int n,i=0,j=0,k;

7 cin>>n;

Page 131: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

131

8 do{

9 while(!q.empty()&&q.front()==j+1){

10 q.pop();j++;}

11 if(i<n)cin>>k;

12 i++;

13 if(k==j+1)j++;

14 else q.push(k);

15 }while(i<=n);

16 if(j==n)cout<<"YES";

17 else cout<<"NO"; }

Сайт acmp, Курсы/Решение олимпиадных задач/С++ Standart

Template Library/Структуры данных

Задача А. Полка (acmp-946)

У Андрея есть младший брат Ванечка, который очень любит

смотреть мультики. Ванечка вечно разбрасывал по дому и терял

свои DVD с мультиками. Поэтому на день рождения Андрей

подарил брату длинную полку для того, чтобы Ванечка ставил на

нее свои диски. Чтобы на полке был порядок, Андрей просил

Ванечку соблюдать простой порядок:

если на полке нет ни одного диска, то Ванечка просто ставит его;

если диск есть, то Ванечка ставит диск либо справа, либо слева от

уже расставленных;

забирает диски он так же, то есть снимает только с правого или

левого края.

И теперь Андрей хочет узнать, выполнил Ванечка его инструкции

или нет.

Входные данные. В первой строке указано целое число N (1 ≤ N ≤

10000) - количество операций, которые выполнил Ванечка. Далее

в N строках находится информация об операциях. Каждая

операция постановки диска на полку описывается парой чисел.

Первое из них (1 или 2) показывает, что диск ставится с левого

края или с правого края соответственно. Второе целое число (от 0

до 10000) обозначает номер диска. Операции снятия диска с полки

Page 132: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

132

описывается одним числом 3 или 4, обозначающим с левого и

правого края полки соответственно снимается диск.

В начальный момент полка пуста. Гарантируется, что

последовательность операций корректна, нет команд снятия диска

с пустой полки.

Выходные данные. Для каждой операции снятия диска с полки

вывести его номер.

Примеры

№ Ввод Вывод

1 5 3 2

1 1

2 2

1 3

3

4

2 2 1

1 1

3

1 #include<iostream>

2 #include<deque>

3 using namespace std;

4 main(){

5 int n,k,d;deque<int>s;

6 cin>>n;

7 for(;n>0;--n){

8 cin>>k;

9 switch(k){

10 case 1:cin>>d;

11 s.push_front(d);break;

12 case 2:cin>>d;

13 s.push_back(d);break;

14 case 3:cout<<s.front()<<' ';

15 s.pop_front();break;

16 case 4:cout<<s.back()<<' ';

17 s.pop_back(); } } }

Page 133: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

133

10.5. МНОЖЕСТВА

Сайт acmp. «Курсы/Язык программирования С++/Массивы»

Тема «Преобразование и анализ». Задача J. Пересечение

множеств (82)

Даны два неупорядоченных набора целых чисел (может быть, с

повторениями). Выдать без повторений в порядке возрастания все

те числа, которые встречаются в обоих наборах.

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

целых числа N и М (1 ≤ N, М ≤ 300 000) — количество элементов

первого и второго наборов соответственно. В следующих строках

записаны сначала N чисел первого набора, а затем M чисел второго

набора. Числа разделены пробелами или символами конца строки.

Каждое из этих чисел попадает в промежуток от 0 до 105.

Выходные данные. Записать в возрастающем порядке без

повторений все числа, которые входят как в первый, так и во

второй набор. Числа разделять одним пробелом. Если таких чисел

нет, не выводить ничего.

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

11 6 6 12

2 4 6 8 10 12 10 8 6 4 2

3 6 9 12 15 18

Из-за возможно больших количеств вводимых и выводимых

чисел для ускорения воспользуемся стандартными функциями

ввода-вывода С. 1 #include<stdio.h>

2 #include<set>

3 using namespace std;

4 main(){

5 int e,N,M; set<int>a,b;

6 scanf("%d%d",&N,&M);

7 while(N){ N--;

8 scanf("%d",&e); a.insert(e);}

9 while(M){ M--;

10 scanf("%d",&e); b.insert(e);}

11 for(auto d:a)

12 if(b.count(d))printf("%d ",d);}

Page 134: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

134

Можно использовать стандартный алгоритм пересечения

множеств:

1 #include<stdio.h>

2 #include<set>

3 #include<algorithm>

4 using namespace std;

5 main(){

6 int e,N,M; set<int>a,b,c;

7 scanf("%d%d",&N,&M);

8 for(;N>0;--N){scanf("%d",&e);a.insert(e);}

9 for(;M>0;--M){scanf("%d",&e);b.insert(e);}

10 set_intersection(a.begin(),a.end(),

11 b.begin(),b.end(),inserter(c,c.end()));

12 for(auto d:c)printf("%d ",d); }

При проверке приведённых выше вариантов решения задачи

мы можем столкнуться с тем, что эти программы слишком долго

работают и не укладываются в ограничения по времени. Это

можно объяснить тем, что структуры set реализованы на бинарных

«красно-чёрных» деревьях. Их достоинством, в частности,

является то, что данные в них автоматически сортируются, но

обрабатываются они со скоростью O(log2N).

Попробуем вместо них использовать реализованные на хэш-

таблицах структуры неотсортированных данных unordered_set со

скоростью доступа О(1), а результат перед выдачей отдельно

отсортируем в соответствующем векторе.

Для краткости вместо длинного списка заголовочных файлов #include<unordered_set>

#include<vector>

#include<algorithm>

воспользуемся сводным файлом #include<bits/stdc++.h>,

но сушественный для скорости работы ввода-вывода

заголовочный файл #include<stdio.h> оставим первым.

Page 135: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

135

1 #include<stdio.h>

2 #include<bits/stdc++.h>

3 using namespace std;

4 main(){ int n,m,x;

5 unordered_set<int>a,b;vector<int>c;

6 scanf("%d%d",&n,&m);

7 for(;n;--n){scanf("%d",&x);a.insert(x);}

8 for(;m;--m){scanf("%d",&x);

9 if(a.count(x))b.insert(x);}

10 for(auto e:b)c.push_back(e);

11 sort(c.begin(),c.end());

12 for(auto e:c)printf("%d ",e);}

Сайт acmp, «Курсы/Решение олимпиадных задач/С++

Standart Template Library»

Тема «Структуры данных». Задача D. Строки-2 (87)

Задан набор строк S = {s1, s2, s3, ... , sn}. Необходимо найти

количество строк si из S, представимых в виде конкатенации двух

строк sj и sk из S (si = sjsk, j и k при этом могут совпадать).

Входные данные. Набор строк S – по одному элементу на строке.

i-ая строка входного файла содержит si. Последняя строка

входного файла содержит строку ENDOFINPUT. Она обозначает

конец входных данных и не входит в S. Все si состоят только из

маленьких букв английского алфавита и имеют длину от 1 до 100

символов. Во входном файле не более 240 строк (включая строку,

содержащую ENDOFINPUT).

Выходные данные. Ответ без ведущих нулей.

Примеры

№ Ввод Вывод

1 aa 2

aaaa

ab

abaa

ENDOFINPUT

Page 136: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

136

2 abc 0

bcd

def

ENDOFINPUT

1 #include<iostream>

2 #include<vector>

3 #include<set>

4 using namespace std;

5 main(){

6 string s;int i,d,k=0;

7 vector<string>v;set<string>m;

8 cin>>s;

9 do{v.push_back(s);m.insert(s);cin>>s;

10 }while(s!="ENDOFINPUT");

11 for(auto t:v){

12 d=t.size();

13 for(i=1;i<d;i++)

14 if(m.count(t.substr(0,i))&&

15 m.count(t.substr(i,d-i))){

16 k++;break;} }

17 cout<<k;}

Сайт ipc. Задача Поиск совпадений (ipc-80)

Даны два текста. Найти все слова, которые встречаются в обоих

текстах сразу. Словом будем называть последовательность из

прописных и строчных латинских букв (максимальная длина слов

– 50 символов). Регистр букв игнорируется.

x-ray состоит из 2 слов X и RAY

Mary's состоит из 2 слов MARY и S

Ввод. В первой строке содержится первый текст, во второй строке

– второй текст. Длина любого из текстов не превышает 100000

символов.

Вывод. В первой строке перечислить в лексикографическом

порядке все слова, встречающиеся в обоих текстах сразу, разделяя

Page 137: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

137

их одним пробелом. Слова выводятся строчными буквами. Если

таких слов нет, вывести пустую строку.

Пример ввода

The tail wagging the dog.

The quick fox jumped over the lazy brown dog.

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

dog the

Сайт ipc. Задача Шпионское сообщение (ipc-141)

Шпионы условились, что будут пересылать друг другу сообщения,

скрывая их в тексте обычного письма. Для секретных сообщений

они решили использовать первые буквы слов из некоторого

набора, а остальные слова в письме использовать для сокрытия

сообщения.

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

используя информацию о наборе слов и текст письма.

Ввод. В первой строке содержится одно целое число N (10 ≤ N ≤

1000). Далее следует N строк, в каждой строке содержится часть

слова, состоящая только из строчных латинских букв. Длина

подслов не превышает 15 букв. Далее до конца файл следует текст

письма. Секретное сообщение составляют первые буквы слов в

письме, которые начинаются с указанных подслов. В письме

используются только латинские буквы (регистр букв не важен) и

знаки препинания. Слова разделяются пробелами, символами

перехода на новую строку и знаками препинания (текст "x-ray"

содержит два слова "x" и "ray"). Количество слов в тексте не

превышает 100 000, длина строки текста не более 250 символов, а

длина слова не более 25 символов.

Вывести одну строку – секретное сообщение. Буквы в сообщении

должны быть строчными.

Page 138: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

138

Пример ввода

10

ec

mari

tor

indu

nec

age

unse

see

goo

mal

Dear John

I hear malicious news about ecological and economic problems in

the South because of the tornado. Indubitable it would

necessitate acting as a goody, but the age forbids me living

in the torrid zone. However Maria has unseasonable longing to

see eccentric unseemly Malibu.

Best regards, Bill

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

meetingatmuseum

Page 139: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

139

10.6. АССОЦИАТИВНЫЕ МАССИВЫ И ЛАМБДА-

ФУНКЦИЯ

Задача О. Олимпиада

Проверяющая система олимпиады по программированию

сообщает жюри о принятых решениях участников

последовательностью строк вида <Имя> <Задача>. Составить на

основании этих данных таблицу результатов олимпиады.

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

Дима А 1 Федя 4

Федя С 2 Дима 3

Дима Е 3 Артур 2

Артур В

Федя А

Артур Е

Артур Е

Федя В

Дима С

Федя D

Для корректной работы с кодами кириллицы вызовем

системную функцию setlocale с соответствующими параметрами.

Для хранения входных данных используем ассоциативный массив,

где ключу – имени участника будет соответствовать множество

сданных им задач. Для сортировки участников по числу решённых

задач сначала сохраним их имена в множестве, затем перепишем

их в вектор, который отсортируем по убыванию результата, для

чего передадим в библиотечную функцию сортировки лямбда-

описание функции сравнения участников по результатам.

Page 140: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

140

1 #include<iostream>

2 #include<map>

3 #include<set>

4 #include<algorithm>

5 using namespace std;

6 main(){

8 setlocale(LC_CTYPE,"Russian");

9 freopen("input.txt","r",stdin);

10 map<string,set<string> > res;

11 string user,task; int i=0;

12 set<string>names; vector<string>table;

13 while(cin>>user>>task){

14 names.insert(user);

15 res[user].insert(task); }

16 for(auto a:names)table.push_back(a);

17 sort(table.begin(),table.end(),

18 [&](string x,string y)->bool{

19 return res[x].size()>=res[y].size(); } );

20 for(auto a:table){ i++;

21 cout<<i<<' '<<a<<' '<<res[a].size()<<endl;}}

Задача О+. Таблица результатов

Представить таблицу результатов в виде:

N A B C D E Всего

1 Федя + + + + – 4

2 Дима + – + – + 3

3 Артур – + – – + 2

Сайт acmp, раздел «Курсы/Язык программирования С++/

Массивы». Тема «Массивы структур».

Задача А. Телефонный справочник (1222)

Мы уже решали эту задачу с помощью сортировки массива

структур по ключу – номеру телефона с последующим бинарным

поиском в отсортированном массиве. Здесь создадим

ассоциативный массив с номером телефона в качестве ключа.

Page 141: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

141

1 #include<stdio.h>

2 #include<map>

3 using namespace std;

4 struct ab{char f[50];char a[50];};

5 main(){int i,j,k,m,n,l,r,t;map<int,ab>a;

6 scanf("%d%d",&n,&m);

7 for(i=0;i<n;++i){ scanf("%d\n",&t);

8 gets(a[t].f);gets(a[t].a);}

9 for(j=0;j<m;++j){ scanf("%d",&k);

10 printf("%s (%s)\n",a[k].f,a[k].a);}}

Сайт acmp, «Курсы/Решение олимпиадных задач/С++

Standart Template Library»

Тема «Структуры данных». Задача Е. Любимая строка (1174)

Исходная строка из N букв разбита на M одинаковых частей.

Найти порядок сборки строки по образцу.

Входные данные. Первая строка содержит два натуральных числа

N и M (N ≤ 106, M ≤ 20 000) – длина строки и количество кусков

соответственно. Во второй строке задана исходная строка S,

состоящая из N строчных букв английского алфавита. Следующие

M строк содержат куски исходной строки, по одному на каждой

строке. Гарантируется, что N делится на M, все куски имеют

одинаковую длину, и из них можно составить строку S.

Выходные данные. Вывести M различных целых чисел ai –

последовательность номеров кусков, в которой их следует

склеивать, чтобы получить исходную строку. Если решений

несколько, вывести любое.

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

12 3 2 3 1

cabacaqwerty

erty

caba

caqw

Указание к решению задачи. Создать ассоциативный массив, где

ключом будет кусочек строки, а значением – вектор позиций

вхождения кусочка в исходную строку.

Page 142: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

142

11. ПЕРЕОПРЕДЕЛЕНИЕ ОПЕРАЦИЙ И ДЛИННАЯ

АРИФМЕТИКА

Будем хранить большие неотрицательные целые числа в

векторах по одной десятичной цифре, при этом в 0-м элементе

вектора будет храниться число, равное цифре из самого младшего

десятичного разряда. Определим необходимые базовые операции

для основных действий с такими длинными объектами. При этом

операции присвоения значения одного длинного другому

длинному и сравнения на равенство (==) и неравенство (!=) двух

длинных переопределять не надо, т.к. они уже определены для

векторов.

#include <iostream>

#include <vector>

#define PB push_back

using namespace std;

// тип длинное целое без знака

typedef vector<int> lll;

// потоковый ввод

istream& operator >>(istream& stream, lll& a){

string s;stream>>s;

for(int i=s.size()-1;i>=0;i--)a.PB(s[i]-48);

return stream;}

// потоковый вывод

ostream& operator <<(ostream& stream, lll

const& a){

for(int i=a.size()-1;i>=0;i--)stream<<a[i];

return stream;}

// сравнение двух длинных

bool operator >(lll const& a, lll const& b){

if(a.size()>b.size())return true;

if(a.size()<b.size())return false;

for(int i=(int)a.size()-1;i>=0;--i){

if(a[i]>b[i])return true;

if(a[i]<b[i])return false; }

return false; }

Page 143: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

143

// сложение двух длинных

lll operator +(lll const& a, lll const& b){

lll c; int i,r,t;

for(i=0,r=0;r||i<a.size()||i<b.size();++i){

if(i<a.size())r+=a[i];

if(i<b.size())r+=b[i];

t=r/10; c.PB(r-t*10); r=t; }

return c; }

// вычитание длинных a>=b

lll operator -(lll const& a, lll const& b){

lll c; int i,r;

for(i=0,r=0;i<a.size();++i){

if(i<a.size())r+=a[i];

if(i<b.size())r-=b[i];

if(r<0){c.push_back(r+10);r=-1;}

else {c.push_back(r);r=0; } }

while(c[c.size()-1]==0)c.resize(c.size()-1);

return c; }

// умножение длинного на короткое

lll operator *(lll const& a, int const& b){

lll c; int i,r,t;

if(b) for(i=0,r=0;r||i<a.size();++i){

if(i<a.size())r+=a[i]*b;

t=r/10; c.PB(r-t*10); r=t; }

else c.PB(0);

return c; }

// умножение длинного на длинное

lll operator *(lll const& a, lll const& b){

lll c,d,e(1,0); int i,j;

if(a==e||b==e)return e;

for(i=0;i<b.size();++i){

c=a*b[i];

for(j=0;j<i;++j)c.insert(c.begin(),0);

d=d+c; }

return c; }

Page 144: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

144

// деление длинного на короткое

lll operator /(lll const& a, int const& b){

lll c; int i,r,t;

for(i=a.size()-1,r=0;i>=0;--i){

r=r*10+a[i]; t=r/b;

c.insert(c.begin(),t); r=r-t*b; }

while(c.size()>1&&c[c.size()-

1]==0)c.resize(c.size()-1);

return c; }

// остаток от деления длинного на короткое

int operator %(lll const& a, int const& b){

int i,r,t;

for(i=a.size()-1,r=0;i>=0;--i){

r=r*10+a[i]; t=r/b; r=r-t*b; }

return r; }

// присвоение длинному значения короткого

void operator =(lll & a, int const& b){

int t=b;

do{ a.PB(t%10); t/=10; }while(t); return a; }

Page 145: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

145

Сайт acmp, «Курсы/Решение олимпиадных задач/Длинная

арифметика»

Тема «Сложение и вычитание». Задачи А..Е

Задача А. Золото племени АББА (7)

Главный вождь племени Абба не умеет считать. В обмен на одну

из его земель вождь другого племени предложил ему выбрать одну

из трех куч с золотыми монетами. Но вождю племени Абба

хочется получить наибольшее количество золотых монет.

Помогите вождю сделать правильный выбор!

Входные данные. В первой строке записаны три натуральных

числа через пробел. Каждое из чисел не превышает 10100. Числа

записаны без ведущих нулей.

Выходные данные. Вывести одно целое число — максимальное

количество монет, которые может взять вождь.

Примеры

№ Ввод Вывод

1 5 7 3 7

2 987531 234 86364 987531

3 189285 283 58439238923098349024 58439238923098349024

Ранее при решении этой задачи предлагалось сравнивать

строки. Используем сейчас приведённые выше коды

переопределения операций и сравним числа, какими длинными

они бы ни были:

#include<iostream>

#include<vector>

#define PB push_back

using namespace std;

typedef vector<int> lll;

istream& operator >>(istream& stream,lll& a)

{...}

ostream& operator <<(ostream& stream,

lll const& a){...}

bool operator >(lll const& a,lll const& b){...}

Page 146: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

146

main(){

lll a,b,c;

cin>>a>>b>>c;

if(b>a)swap(a,b);

if(c>a)swap(a,c);

cout<<a;}

Решить задачи

B 103 Снова А+В

C 535 Неправильное сложение

D 143 А-В

E 541 Две строки

Page 147: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

147

Сайт acmp, «Курсы/Решение олимпиадных задач/Длинная

арифметика»

Тема «Умножение и деление». Задачи А..I

Задача А. 2^N (40)

Необходимо вычислить значение 2n.

Входные данные. Натуральное число n (0 < n < 1000).

Выходные данные. Значение 2n.

Примеры

№ Ввод Вывод

1 3 8

2 10 1024

3 73 4722366482869645213696

#include <iostream>

#include <vector>

#define PB push_back

using namespace std;

typedef vector <int> lll;

ostream& operator <<(ostream& stream, lll a)

{...}

lll operator *(lll a,ll b) {...}

void operator =(lll & a, int const& b){...}

main () {

lll a=1; int n; cin>>n;

while(n){n--; a=a*2;}

cout<<a; }

Решить задачи

B 144 A*B

C 172 Деление с остатком

D 145 А div В

Page 148: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

148

Задача Е. Цифры после запятой (acmp-803)

По заданным натуральным числам A и B найти K-ю цифру после

запятой в дроби A/B в десятичной системе счисления.

Входные данные. Три натуральных числа A, B и K через пробел.

А и B – цифры (числа от 1 до 9), число K не превышает 106.

Примеры

№ Ввод Вывод

1 7 4 2 5

2 1 6 13 6

К числителю А допишем К нулей и поделим на В. Старшая

цифра результата будет ответом, а остальные цифры нам не

нужны.

1 #include <iostream>

2 #include <vector>

3 using namespace std;

4 main(){

5 int a,b,k,i,t,r=0;

6 cin>>a>>b>>k;

7 vector<int> c(k,0);

8 c.push_back(a);

9 for (i=c.size()-1;i>=0;--i){

10 r=r*10+c[i]; t=r/b; r-=t*b;}

11 cout<<t; }

Решить задачи

F 363 Длинное произведение

G 109 А/В

H 75 Сумма произведений

I 146 Длинный корень

Page 149: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

149

РЕКОМЕНДУЕМАЯ ЛИТЕРАТУРА

1. Васильев, А. Н. Самоучитель С++ с примерами и задачами

[Текст] / А. Н. Васильев. – 4-е изд., перераб. – Санкт-Петербург :

Наука и техника, 2016. – 480 с.

2. Вирт, Н. Алгоритмы и структуры данных [Текст] : пер. с англ. /

Н. Вирт. – Москва : ДМК Пресс, 2016. – 272 с.

3. Кормен, Т. Алгоритмы. Построение и анализ [Текст] : пер. с

англ. / Т. Кормен, Ч. Лейзерсон, Р. Ривест, К. Штайн. – 3-е изд.

– Москва : Вильямс, 2016. – 1324 с.

4. Липпман, С. Б. Язык программирования С++. Базовый курс

[Текст] : пер. с англ. / С. Б. Липпман, Ж. Лажойе, Б. Э. Му. –

Москва : Вильямс, 2017. – 1120 с.

5. Меньшиков, Ф. В. Олимпиадные задачи по программированию

[Текст] / Ф. В. Меньшиков. – Санкт-Петербург : Питер, 2006. –

315 с.

6. Окулов, С. М. Основы программирования [Электронный ресурс] /

С. М. Окулов. – Москва : Лаборатория знаний, 2015. – 339 с. –

Режим доступа : http://e.lanbook.com/book/66119 (01.04.2018).

7. Павловская, Т. А. С/С++. Программирование на языке высокого

уровня [Текст] : учебник для вузов / Т. А. Павловская. – Санкт-

Петербург : Питер, 2008. – 459 с.

8. Подбельский, В. В. Стандартный Си++ [Электронный ресурс] :

учебное пособие / В. В. Подбельский. – Москва : Финансы и

статистика, 2008. – 688 с. – Режим

доступа : //biblioclub.ru/index.php?page=book&id=226131

(01.04.2018).

9. Скиена, С. Алгоритмы. Руководство по разработке [Текст] : пер.

с англ. / С. Скиена. – 2-е изд. – Санкт-Петербург : БХВ-

Петербург, 2011. – 720 с.

10. Слабнов, В. Д. Программирование на С++ [Электронный

ресурс] : лекции / В. Д. Слабнов ; Институт экономики, управления

и права (г. Казань). – Казань : Познание, 2012. – 136 с. – Режим

доступа : //biblioclub.ru/index.php?page=book&id=364222

(01.04.2018).

Page 150: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

150

11. Страуструп, Б. Язык программирования С++ [Текст] :

специальное издание / Б. Страуструп ; пер. с англ.

Н. Мартынова. – Москва : Бином-Пресс, 2015. – 1136 с.

12. Хабибуллин, И. Ш. Программирование на языке высокого

уровня С/С++ [Текст] : учебное пособие / И. Ш. Хабибуллин. –

Санкт-Петербург : БХВ-Петербург, 2006. – 512 с.

13. Шилдт, Г. С++ для начинающих. Шаг за шагом [Текст] :

самоучитель / Г. Шилдт ; пер. с англ. К. Финогенова. – Москва :

ЭКОМ Паблишерз, 2013. – 640 с.

14. Шень, А. Х. Практикум по методам построения алгоритмов

[Электронный ресурс] : курс / А. Х. Шень. – Москва : Интернет-

университет информационных технологий, 2009. – 289 с. – Режим

доступа : http://biblioclub.ru/index.php?page=book&id=234674

(01.04.2018).

15. Шень, А. Х. Программирование: теоремы и задачи

[Электронный ресурс] / А. Х. Шень. – 6-е изд., доп. – Москва :

Издательство МЦНМО, 2017. – 320 с. – Режим доступа :

https://hal.archives-ouvertes.fr/hal-01480636/document

(01.04.2018).

Page 151: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

151

ЭЛЕКТРОННЫЕ РЕСУРСЫ

16. Школа программиста [Электронный ресурс] : сайт /

С. Н. Беляев, ККДП – Красноярск, 2003–. – Режим доступа :

https://acmp.ru/, свободный (01.04.2018).

17. Informatics, Programming, Contests [Электронный ресурс] :

сайт / А. К. Демидов, НИУ ЮУрГУ – Челябинск, 1997–. – Режим

доступа : http://ipc.susu.ru/, свободный (01.04.2018).

18. Справочник по С++ по-английски с примерами

[Электронный ресурс] : сайт. – Режим доступа :

http://www.cplusplus.com//, свободный (01.04.2018).

19. Справочник по С++ по-русски [Электронный ресурс] : сайт.

– Режим доступа: http://ru.cppreference.com/w/, свободный

(01.04.2018).

20. Язык программирования Си. Практический курс

[Электронный ресурс] : сайт / К. Ю. Поляков, Санкт-Петербург,

2000–. – Режим доступа : http://kpolyakov.spb.ru/school/c.htm,

свободный (01.04.2018).

21. Интернет-университет информационных технологий

[Электронный ресурс] : сайт / НОУ «ИНТУИТ». – Москва,

2003–. – Режим доступа : http://www.intuit.ru/, свободный

(01.04.2018).

22. MAXimal [Электронный ресурс] : сайт / М. Иванов. – [Б. м.,

2007–2012]. – Режим доступа : http://e-maxx.ru/algo/, свободный

(01. 04.2018).

23. ALGOLIST.MANUAL.RU. Алгоритмы и методы

[Электронный ресурс] : сайт / И. Кантор. – [Б.м., 2000–2007]. –

Режим доступа : http://algolist.ru/, свободный (01. 04.2018).

24. Дистанционная подготовка по информатике [Электронный

ресурс] : сайт / ЦПМ, МЦНМО – Москва, 2006–. – Режим

доступа: http://informatics.msk.ru/, свободный (01.04.2018).

Page 152: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

152

25. IDE Dev-C++ [Электронный ресурс] : сайт. – Режим доступа :

http://orwelldevcpp.blogspot.ru/, свободный (01. 04.2018).

26. MinIDE [Электронный ресурс] : сайт. – Режим доступа :

https://ipc.susu.ru/learn.html, свободный (01. 04.2018).

27. Web-IDE для программирования на С++ [Электронный

ресурс] : сайт. – Режим доступа : http://cpp.sh/, свободный

(01.04.2018).

28. Web-IDE для программирования на С++ и других языках

[Электронный ресурс] : сайт. – Режим доступа :

https://ideone.com/, свободный (01.04.2018).

29. Web-IDE для программирования на С++ и других языках

[Электронный ресурс] : сайт. – Режим доступа :

https://www.jdoodle.com/, свободный (01.04.2018).

30. Алексеев, М. Н. [Электронный ресурс] // Челябинский

государственный университет : сайт. — Челябинск, 2011–. –

Режим доступа : http://math.csu.ru/~alexeev/, свободный

(01.04.2018).

31. Тест по языку программирования С++ [Электронный ресурс]

/ М. Н. Алексеев // Челябинский государственный университет

: сайт. – Челябинск, 2014–. – Режим доступа :

http://moodle.uio.csu.ru/course/view.php?id=1101, из сети ЧелГУ

или, после регистрации из сети ун-та, из любой точки, имеющей

доступ в Интернет (01.04.2018).

Page 153: F B G H ; J G : M D B N ^ j Z e v g h ] h k m ^ Z j [ x ...math.csu.ru › ~alexeev › arc › pracpp.pdf · 2 M > D 004.432.2 ; ; 32.973.26-018.1 73 47 Алексеев, М. Н

153

Учебное издание

Алексеев Михаил Николаевич

Алексеева Татьяна Михайловна

ПРАКТИКУМ ПО ПРОГРАММИРОВАНИЮ НА ЯЗЫКЕ С++

Учебное пособие

Печатается по решению Ученого совета

Миасского филиала ФГБОУ ВО «ЧелГУ»

Протокол № 1 от 08.04.2018

Редактор Л.В. Попова

Компьютерная вёрстка Т. М. Алексеевой

Подписано в печать 27.04.2018

Формат 60×841/16. Бумага офсетная.

Печать офсетная. Усл. печ. л. 3,8. Уч.-изд. л. 3,7.

Тираж 60 экз. Заказ __

Цена договорная

ООО «Геотур»

456320 Челябинская обл., г. Миасс, Октября, д. 31, кв. 20

Лицензия № 063431 от 25.08.1999

Отпечатано на полиграфической базе

АО «ГРЦ Макеева»

456300 Челябинская обл., г. Миасс, Тургоякское шоссе, 1