e-olymp 7447. Обрезка строки

Задача с сайта e-olymp.com.

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

Имеется строка [latex]s[/latex]. Разрешается взять два любых одинаковых соседних символа и удалить их из строки. Эту операцию можно производить пока имеется возможность. Сначала Вы можете выбрать любое количество символов в строке и удалить их. Определить наименьшее количество символов, которое Вы можете удалить сначала так, чтобы затем выполняя разрешенную операцию, получить пустую строку.

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

Содержит строку [latex]s[/latex] ([latex]1 ≤[/latex] длина[latex]\left( s \right) [/latex] [latex]≤ 100)[/latex].

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

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

Тесты

Входные данные Выходные данные
1 abbcddka 2
2 ABBA 0
3 abcde 5
4 abbac 1

Код на C++

Код на Java

Описание

Идея решения состоит в том, чтобы разбить строку на меньшие по длине подстроки и найти ответ на задачу для каждой из них. Для хранения строки используется переменная s, а ответы на подзадачи содержатся в двумерном массиве целых чисел answers. В answers[i][j] находится ответ для подстроки с i-ого по j-й символ включительно. В функции main сначала вводится строка s. Далее ширина и глубина массива answers устанавливаются равными длине s. После этого он заполняется начальными значениями. Значение [latex]-1[/latex] означает, что ответ для этой ячейки ещё не был найден. Однако очевидно, что если строка состоит ровно из одного символа, согласно условию задачи, его придётся удалить, значит, главную диагональ можно сразу заполнить единицами. Затем происходит вызов рекурсивной функции calculate, принимающей индексы левой и правой границ целевой подстроки. Первый раз она вызывается для всей строки от первого до последнего символа. Работает эта функция следующим образом: если индекс левой границы отрезка больше индекса правой, что, в случае данной задачи, не имеет смысла, она возвращает ноль. Иначе она возвращает ответ на задачу для данной подстроки, а если этого не делалось ранее, то предварительно находит его. Происходит это так: сначала значение ответа устанавливается равным длине подстроки, поскольку в худшем случае необходимо будет удалить её всю целиком. Если символы на концах подстроки одинаковые, они, как сказано в условии, будут удалены в дальнейшем, потому нужно рассматривать минимум из текущего значения ответа и ответа для подстроки без крайних символов. Однако может оказаться, что выгоднее удалить символы из каких-то двух меньших подстрок, потому далее в цикле рассматриваются все возможные комбинации двух подстрок, из которых можно составить конкатенацией текущую. В итоге получаем ответ на задачу для данной подстроки.

Код на ideone.com. (C++)
Код на ideone.com. (Java)
Засчитанное решение на e-olymp.

e-olymp 4496. Приключение Незнайки и его друзей

Задача с сайта e-olymp.com.

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

Все мы помним историю о том, как Незнайка со своими друзьями летали на воздушном шаре путешествовать. Но не все знают, что не все человечки влезли в шар, так как у него была ограниченная грузоподъемность.

В этой задаче Вам необходимо узнать, сколько же человечков улетело путешествовать. Известно, что посадка в шар не является оптимальной, а именно: человечки садятся в шар в той очереди, в которой они стоят, как только кому-то из них не хватает места, он и все оставшиеся в очереди разворачиваются и уходят домой.

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

В первой строке содержится количество человечков [latex]n (1 ≤ n ≤ { 10 }^{ 6 })[/latex] в цветочном городе. Во второй строке заданы веса каждого из человечков в том порядке, в котором они будут садиться в шар. Все веса натуральные числа и не превышают [latex]{ 10 }^{ 9 }[/latex]. Далее следует количество запросов [latex]m (1 ≤ m ≤ { 10 }^{ 5 })[/latex]. Каждый запрос представляет собой одну строку. Если первое число в строке равно единице, то далее следует еще одно число [latex]v (1 ≤ v ≤ { 10 }^{ 9 })[/latex] – грузоподъемность воздушного шара. Если же оно равно двум, то далее следует два числа [latex]x (1 ≤ x ≤ n)[/latex] и [latex]y (1 ≤ y ≤ { 10 }^{ 9 })[/latex] — это значит, что вес человечка, стоящего на позиции [latex]x[/latex], теперь равен [latex]y[/latex].

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

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

Тесты

Входные данные Выходные данные
1 5
1 2 3 4 5
5
1 7
1 3
2 1 5
1 7
1 3
3
2
2
0
2 2
1 2
3
1 4
2 1 10
1 4
2
0
3 2
999999999 1000000000
4
1 999999999
2 1 1000000000
1 999999999
1 1000000000
1
0
1

Код на C++

Код на Java

Описание

В данной задаче требуется эффективно выполнять две операции: изменять значение одного из элементов массива и находить, сколько человечков поместится в шар при заданной грузоподъёмности. Это было реализовано при помощи структуры segment_tree. В функции main сначала вводится значение n и заполняется массив весов человечков weights, после чего по нему выполняется построение дерева отрезков tr. В его вершинах хранятся частичные суммы элементов массива. Да и в целом функции для построения и выполнения запроса модификации у него такие же, как и у обычного дерева отрезков для нахождения суммы на отрезке. Для удобства в массиве weights и в самом дереве используются элементы с первого по [latex]n[/latex]-й, а не с нулевого по [latex]\left( n-1 \right) [/latex]-й. Далее в ходе работы функции main в цикле выполняется обработка запросов. Сначала вводится тип запроса type. Если запрос второго типа, вводятся позиция человечка x, его новый вес y и вызывается метод update, пересчитывающий значения суммы в вершинах, на которые влияет это изменение. Иначе вводится грузоподъемность воздушного шара v и вызывается метод find_numb_of_p, который находит количество человечков, поместившихся в шар. Работает он следующим образом: если выполняется условие tree_l == tree_r, значит, рассматриваемый отрезок состоит из одного элемента, и функция возвращает [latex]1[/latex], если человечек может поместиться в шар, и [latex]0[/latex], если он слишком тяжёлый. Если отрезок больше, вычисляется индекс элемента, находящегося посередине tree_m. Далее, если сумма весов человечков в левом поддереве tree[v*2] больше, чем грузоподъёмность шара, то никто из правого поддерева уже не поместится, и искать следует только в левом поддереве. Иначе в шар следует посадить всех человечков из левого поддерева (их количество равно tree_m - tree_l + 1) и посмотреть, сколько поместится человечков из правого поддерева. При этом необходимо от максимально допустимого веса отнять вес человечков из левого поддерева, уже сидящих в шаре ( max_w-tree[v*2]).

Код на ideone.com. (C++)
Засчитанное решение на e-olymp.com. (C++)
Код на ideone.com. (Java)
Засчитанное решение на e-olymp.com. (Java)
При решении задачи был использован материал с сайта e-maxx.ru.

e-olymp 1075. Умножение многочленов

Задача с сайта e-olymp.com.
Засчитанное решение. (C++)
Засчитанное решение. (Java)

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

Вводится в символьной форме два многочлена от [latex]x[/latex] с целыми коэффициентами. Вывести их произведение в порядке убывания степеней — также в символьной форме. Степень исходных многочленов не более [latex]10[/latex], коэффициенты исходных многочленов по модулю не более [latex]{ 10 }^{ 4 }[/latex].

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

В двух строках находятся многочлены.

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

В единственной строке выводится многочлен.

Тесты

Входные данные Выходные данные
1 0
0
0
2 x+1
x-1
x^2-1
3 -5
x^2+x+x-2x^3
10x^3-5x^2-10x
3 x^10+2x^9+3x^8
-1
-x^10-2x^9-3x^8
4 x^10+2x^9+3x^8
0
0
5 x^10+5x^2
x^3-4x
x^13-4x^11+5x^5-20x^3

Решение с использованием класса string

Код программы

Нажмите, чтобы выполнить его на ideone.com.

Описание

Сначала в функции main объявляются две строки a и b. В них водятся исходные два многочлена. Но в форме строк, особенно учитывая, что подобные слагаемые не всегда приведены, умножать многочлены не удобно. Потому объявляются три вектора: a_decomposed, b_decomposed
и c_decomposed. Первые два имеют размер [latex]11[/latex], поскольку в условии сказано, что многочлены могут быть от нулевой до десятой степени включительно. В них элемент с индексом [latex]i[/latex] равняется коэффициенту при слагаемом многочлена, в котором [latex]x[/latex] имеет степень [latex]i[/latex]. Они заполняются при помощи функции decompose. В ней при помощи функции analyze отдельно анализируется каждое слагаемое многочлена, и результат заносится в вектор. c_decomposed хранит коэффициенты многочлена, полученного умножением двух исходных. Значения его элементов вычисляются при помощи функции multiplicate. После в ходе работы функции compose многочлен в требуемой форме записывается в строку c. Далее, если её первым символом является [latex]+[/latex], он удаляется из строки. Наконец, если c — непустая строка, она выводится. Иначе выводится [latex]0[/latex].

Решение с использованием c-string

Код программы

Нажмите, чтобы выполнить его на ideone.com.

Описание

Алгоритм решения тот же. Следует отметить: поскольку объекты типа char* «не знают» свою длину, и в силу других причин, в некоторых местах программы используются «магические числа». Однако они не взяты случайно, а продиктованы условием задачи (к примеру, тем, что максимальная степень исходных многочленов — [latex]10[/latex] и т.п.). Только подходящее значение переменной max_number_of_symbols было найдено эмпирически.

Решение на Java

Код программы

Нажмите, чтобы выполнить его на ideone.com.

e-olymp 595. Новый Лабиринт Амбера

Задача с сайта e-olymp.com

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

Как-то Корвину – принцу Амбера, по каким-то важным делам срочно понадобилось попасть в самую далекую тень, которую он только знал. Как всем известно, самый быстрый способ путешествия для принцев Амбера – это Лабиринт Амбера. Но у Корвина были настолько важные дела, что он не хотел тратить время на спуск в подземелье (именно там находится Амберский Лабиринт). Поэтому он решил воспользоваться Новым Лабиринтом, который нарисовал Дворкин. Но этот Лабиринт не так прост, как кажется…

Новый Лабиринт имеет вид последовательных ячеек, идущих друг за другом, пронумерованных от [latex]1[/latex] до [latex]N[/latex]. Из ячейки под номером [latex]i[/latex] можно попасть в ячейки под номерами [latex]i+2[/latex] (если [latex]i+2 ≤ N[/latex]) и [latex]i+3[/latex] (если [latex]i+3 ≤ N[/latex]). На каждой ячейке лежит какое-то количество золотых монет [latex]{ k }_{ i }[/latex]. Для того чтобы пройти лабиринт нужно, начиная ходить из-за границ лабиринта (с нулевой ячейки) продвигаться по выше описанным правилам, при этом подбирая все монетки на ячейках, на которых вы делаете промежуточные остановки. Конечная цель путешествия – попасть на ячейку с номером [latex]N[/latex]. Дальнейшее путешествие (в любое место Вселенной) возможно лишь тогда, когда достигнув ячейки с номером [latex]N[/latex], вы соберете максимально количество монеток. Напишите программу, которая поможет Корвину узнать, какое максимальное количество монеток можно собрать, проходя Новый Лабиринт Амбера.

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

В первой строке входного файла содержится натуральное число [latex]N (2 ≤ N ≤ 100000)[/latex], а во второй [latex]N[/latex] целых чисел, разделенных одним пробелом, [latex]{ k }_{ i }[/latex] – количество монеток, лежащих в ячейке с номером [latex]i[/latex] [latex](0 ≤ i ≤ 1000)[/latex].

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

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

Тесты

Входные данные Выходные данные
1 5
1000 2 3 1 3
6
2 2
1 2
2
3 4
1 3 100 0
3

Решение с использованием цикла

Код программы

Засчитанное решение на e-olymp.com.

Описание

Для хранения количества монет в каждой ячейке лабиринта используем массив [latex]dp[/latex] длиной [latex]n+1[/latex] элементов. При этом каждой ячейке лабиринта соответствует ячейка массива с тем же индексом, а нулевой элемент массива понимаем как точку перед входом в лабиринт. В цикле считываем количество монет в каждой ячейке, после чего обнуляем значение нулевого элемента массива, поскольку ячейка, соответствующая ему, находится вне лабиринта, и первого, поскольку в ячейку, соответствующую ему, невозможно попасть никаким образом. Далее в цикле для каждой ячейки лабиринта находим, какое максимальное количество монет может быть у Корвина после её посещения. В ячейку с номером [latex]i[/latex] он может попасть или из ячейки с номером [latex]i-2[/latex], или из ячейки с номером [latex]i-3[/latex]. При этом он несёт с собой все собранные ранее монеты, и добавляет к ним те, что находятся в данной ячейке. Таким образом, формула для нахождения максимального количества монет после посещения [latex]i[/latex]-й ячейки имеет вид [latex]dp[i] = dp[i] + max(dp[i-2], dp[i-3])[/latex], и ответ к задаче хранится в [latex]n[/latex]-й ячейке массива. Дополнительно требуется проводить проверку на выход за границы массива.

Код на ideone.com.

Решение с использованием рекурсивной функции

Код программы

Засчитанное решение на e-olymp.com.

Описание

В данном случае используется функция [latex]f[/latex], принимающая номер ячейки массива и возвращающая максимальное количество монет после посещения ячейки с этим номером. Сначала объявляются два глобальных массива:
[latex]dp[/latex], в [latex]i[/latex]-й ячейке которого изначально хранится количество монет в [latex]i[/latex]-й ячейке лабиринта, и [latex]used[/latex], элементы которого принимают значения [latex]0[/latex] или [latex]1[/latex] (значение [latex]0[/latex] в [latex]i[/latex]-й ячейке означает, что максимальное количество монет после посещения
ячейки лабиринта с тем же номером рассчитано ещё не было). Далее всё происходит как в решении с использованием цикла, но одновременно с чтением входных данных обнуляются элементы [latex]used[/latex], а вместо второго цикла происходит вызов функции [latex]f[/latex]. Сама же функция [latex]f[/latex], если значение параметра меньше двух, возвращает [latex]0[/latex], а иначе, если этого не было сделано ранее, вычисляет максимальное количество монет после посещения ячейки с номером [latex]i[/latex] по формуле [latex]dp[i] = dp[i] + max(dp[i-2], dp[i-3])[/latex] и возвращает его.

Код на ideone.com.
Кроме того, об идее решения данной задачи можно почитать здесь.

A274. Среднее арифметическое всех членов последовательности, кроме одного

Задача из сборника задач по программированию Абрамова С.А. 2000г.
Даны действительные числа [latex]a_{ 1 }[/latex],…,[latex]a_{ 20 }[/latex]. Получить числа [latex]b_{ 1 }[/latex],…,[latex]b_{ 20 }[/latex], где [latex]b_{ i }[/latex] – среднее арифметическое всех членов последовательности [latex]a_{ 1 }[/latex],…,[latex]a_{ 20 }[/latex], кроме [latex]a_{ i }[/latex] ([latex]i[/latex] = 1,2,…,20).

Обобщим задачу для последовательности длины [latex]n[/latex]
Даны действительные числа [latex]a_{ 1 }[/latex],…,[latex]a_{ n }[/latex]. Получить числа [latex]b_{ 1 }[/latex],…,[latex]b_{ n }[/latex], где [latex]b_{ i }[/latex] – среднее арифметическое всех членов последовательности [latex]a_{ 1 }[/latex],…,[latex]a_{ n }[/latex], кроме [latex]a_{ i }[/latex] ([latex]i[/latex] = 1,2,…,[latex]n[/latex]).

Входные данные:
Последовательность действительных чисел.

Выходные данные:
[latex]n[/latex] чисел, [latex]i[/latex]-ое из которых является средним арифметическим всех членов последовательности, кроме [latex]i[/latex]-го ([latex]i[/latex] = 1,2,…,[latex]n[/latex]).

Тесты

Входные данные Выходные данные
1 4 The sequence must consist of at least two elements.
2 1 0 1 The arithmetic average of all elements of this series except the element №i is:
for i = 1: 0.5
for i = 2: 1
for i = 3: 0.5
3 10.1 2.4 11.3 0.8 The arithmetic average of all elements of this series except the element №i is:
for i = 1: 4.8(3)
for i = 2: 7.4
for i = 3: 4.4(3)
for i = 4: 7.9(3)
4 2.5 -1.5 4 -9 1.22 The arithmetic average of all elements of this series except the element №i is:
for i = 1: -1.32
for i = 2: -0.32
for i = 3: -1.695
for i = 4: 1.555
for i = 5: -1

Код на C++

Код на Java

Решение
Для начала, в первом цикле мы читаем числа из входного потока, помещаем их в вектор a и прибавляем к переменной sum, предназначенной для хранения суммы всех чисел последовательности. Последовательность должна состоять как минимум из двух элементов. Чтобы получить среднее арифметическое всех её членов, кроме [latex]i[/latex]-го, достаточно отнять [latex]i[/latex]-й элемент вектора a от значения переменной sum и разделить результат на количество членов такой неполной последовательности, а оно будет на единицу меньше размера вектора a. Таким образом заполняется вектор b, в котором хранятся элементы последовательности [latex]b_{ 1 }[/latex],…,[latex]b_{ n }[/latex], после чего требуемая последовательность выводится.

Код на ideone.com (C++)
Код на ideone.com (Java)
Условие задачи (с.118)

MS15. Зашифровка и расшифровка текста

Для решения задания MS15 необходимо, чтобы предыдущее уже было сделанным, однако на момент публикации оно таковым не является, потому данная запись содержит и его решение тоже.

Условие задачи MS14.
Зашифруйте текст из входного потока заменяя каждый символ по формуле [latex]c=at+b \mod 256[/latex], где [latex]t[/latex] — символ открытого текста, [latex]c[/latex] — символ зашифрованного текста, [latex]a[/latex], [latex]b[/latex] — произвольные ключи (параметры) шифрования.

Входные данные:
Два ключа через пробел и, через ещё один пробел, текст.

Выходные данные:
Зашифрованный текст.

Тесты.

Входные данные Выходные данные
[latex]a[/latex] [latex]b[/latex] Исходный текст Зашифрованный текст
1 f n Kittens P▲D*ж.ж.м(B,@.
2 4 j Hello, world! ◙☼ю¶z▬z▬ў▬z○ъ♠ц↑ў▬т↨z▬║¶▲•
3 ? . 0123456789 ■♂=♀|♀╗♀·♀9♪x♪╖♪ў♪5♫

Код на С++

Код на Java

Условие задачи MS15.
Найдите способ и напишите программу расшифровки текста зашифрованного в предыдущем задании по известным [latex]a[/latex] и [latex]b[/latex].

Входные данные:
Два ключа через пробел и, через ещё один пробел, зашифрованный текст.

Выходные данные:
Расшифрованный текст.

Тесты.

Входные данные Выходные данные
[latex]a[/latex] [latex]b[/latex] Зашифрованный текст Расшифрованный текст
1 f n P▲D*ж.ж.м(B,@. Kittens
2 4 j ◙☼ю¶z▬z▬ў▬z○ъ♠ц↑ў▬т↨z▬║¶▲• Hello, world!
3 ? . ■♂=♀|♀╗♀·♀9♪x♪╖♪ў♪5♫ 0123456789

Код на C++

Код на Java

Решение.
Основной трудностью при решении задачи является тот момент, что при шифровке символов строго по формуле, указанной в условии MS14, а именно [latex]c=at+b \mod 256[/latex], символы зашифрованного текста могут расшифровываться неоднозначно. К примеру, при [latex]a=8[/latex] и [latex]b=1[/latex] после зашифровки символов [latex]@[/latex] и [latex]`[/latex] в обоих случаях получим символ с кодом [latex]1[/latex]. Это часто лишает расшифрованный текст какого-либо смысла. Так происходит, поскольку в переменных типа [latex]unsigned[/latex] [latex]char[/latex] могут храниться элементы с кодом от [latex]0[/latex] до [latex]255[/latex], и при попытке присвоить переменной большее значение совершается своеобразный «круг». Так, если ей присвоить значение [latex]257[/latex], при выводе получим символ с кодом [latex]1[/latex]. Сначала в ходе работы обеих программ вводятся два ключа, а лишние пробелы читаются в одну из переменных для хранения символов. Программа для зашифровки принимает символ, зашифровывает его по указанной формуле, и выводит, а сразу за ним — элемент с кодом, который высчитывается по другой формуле: [latex]c=(at+b) / 256[/latex]. Этот код совпадает с числом совершённых «кругов». Программа для расшифровки же на каждом цикле принимает эти два символа, и выводит символ исходного текста, код которого вычисляется округлением до целых значения выражения [latex]\frac { c1-b+256\cdot c2 }{ a } [/latex], где [latex]c1[/latex] — первый символ, а [latex]c2[/latex] — второй.

Условия задач.
Код MS14 на ideone.com(C++)
Код MS15 на ideone.com(C++)
Код MS14 на ideone.com(Java)
Код MS15 на ideone.com(Java)

A327. Простые числа

Задача из сборника задач по программированию Абрамова С.А. 2000г.
Даны натуральные числа [latex]a, b (a\le b)[/latex]. Получить все простые числа [latex]p[/latex], удовлетворяющие неравенствам [latex]a\le p\le b[/latex].

Входные данные:
Два натуральных числа [latex]a[/latex] и [latex]b[/latex].

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

Тесты.

Входные данные Выходные данные
[latex]a[/latex] [latex]b[/latex] [latex]p[/latex]
1 1 4 2, 3
2 0 1 Not found
3 5 5 5
4 6 20 7, 11, 13, 17, 19

Код программы (C++).

Код программы (Java).

Решение.
C++:
Для начала, вводятся два целых числа. Очевидно, что придётся проверять, являются ли простыми числа, большие чем [latex]a[/latex] и меньшие чем [latex]b[/latex]. Не представляется возможным заранее узнать, насколько большими будут эти числа, потому, на мой взгляд, наиболее подходящим решением будет каждый запуск программы заново находить все простые числа до [latex]b[/latex]. Создаётся вектор, в котором они будут храниться (целесообразно использовать именно вектор, поскольку неизвестно точно, сколько чисел придётся хранить). Далее идёт цикл, в котором каждое число от двух до [latex]b[/latex], если оно не делится нацело ни на один из элементов вектора (это проверяется при по мощи вложенного цикла), добавляется в этот вектор и, если оно больше чем [latex]a[/latex], выводится. В случае, если [latex]b<2[/latex], очевидно, простые числа найдены не будут, потому выводится "Not found."
Java:
Решение на Java представляет собой реализацию Решета Эратосфена.
Код на ideone.com: C++, Java.
Условие задачи (с.135)

D2655B. Cумма ряда с заданной точностью

Задача
Сколько примерно надо взять членов ряда, чтобы найти его сумму с точностью до
[latex]\varepsilon [/latex], если [latex]\sum\limits _{ n=1 }^{ \infty }{ \frac { 1 }{ (2n-1)! } } [/latex]

Тесты

Входные данные Выходные данные
Точность Кол-во взятых членов ряда Значение суммы
1 1 2 1.1666666667
2 1е-5 5 1.1752011684
3 100 1 1
4 1e-10 7 1.1752011936

Код на C++

Код на Java

Решение
Очевидно, ряд является положительным, и общий член ряда стремится к нулю. Ряд сходится по признаку Д’аламбера:
[latex] \lim\limits_{n \rightarrow \infty } \frac{ a_{n+1} }{a_{n}} = \lim\limits_{n \rightarrow \infty } \frac{ \big(2n-1\big)! }{ \big(2n+1\big)! } = \lim\limits_{n \rightarrow \infty } \frac{1}{2n \big(2n+1\big) } =0 < 1[/latex].
Оценим остаток ряда, исходя из того, что [latex]k! > \left( \frac{k}{e} \right) ^{k} , \big(k=1,2,\dots\big) [/latex]:
[latex]R_{N}<\sum\limits_{n=N+1}^\infty \left(\frac{e}{2n-1}\right)^{2n-1}\leq\sum\limits_{n=N+1}^\infty \left(\frac{e}{2N+1}\right)^{2n-1}=\left(\frac{e}{2N+1}\right)^{2N+1}\sum\limits_{i=0}^\infty \left(\frac{e}{2N+1}\right)^{2i}[/latex]
Поскольку при [latex]N\geq1[/latex] [latex]\frac{e}{2N+1}<1[/latex]:
[latex]R_{N} < \left(\frac{e}{2N+1}\right)^{2N+1}\frac{1}{1-\left(\frac{e}{2N+1}\right)^2}[/latex]

В переменной sum хранится текущее значение суммы ряда, в last — последний рассмотренный член ряда. В начале работы программы вводится требуемая точность eps. Можно заметить, что для получения [latex]n[/latex]-го члена ряда достаточно разделить предыдущий на [latex]\left(2n-2\right)\cdot\left(2n-1\right)[/latex], однако необходимо отдельно рассмотреть случай, когда [latex]n = 1[/latex]. В цикле увеличиваем [latex]n[/latex], находим значение следующего члена ряда и прибавляем к sum, пока остаток ряда не станет достаточно маленьким. Оцениваем остаток ряда при помощи функции Rn(int n). Во время её работы может потребоваться возведение числа в большую степень, делаем это по алгоритму бинарного возведения в степень.

Ссылка на код на ideone.com: здесь (C++) и здесь (Java).
Условие задачи (стр. 259)

КМ17. Крестьянин на развилке

Задача из журнала «Квант» №4 1970г.

Крестьянин, подойдя к развилке двух дорог, расходящихся под углом 60°, спросил: <Как пройти в село [latex]NN?[/latex]> Ему ответили: <Иди по левой дороге до деревни [latex]N[/latex] — это в восьми верстах отсюда,— там увидишь, что направо под прямым углом отходит большая ровная дорога,— это как раз дорога в [latex]NN[/latex]. А можешь идти другим путём: сейчас по правой дороге; как выйдешь к железной дороге,— значит, половину пути прошёл; тут поверни налево и иди прямо по шпалам до самого NN>. — <Ну, а какой путь короче-то будет?> — <Да всё равно, что так, что этак, никакой разницы.> И пошёл крестьянин по правой дороге. Сколько вёрст ему придётся идти до NN? Больше десяти или меньше? А если идти от развилки до [latex]NN[/latex] напрямик? (Все дороги прямые.)

Более лаконичная версия:
Крестьянин стоит на развилке дорог, которые расходятся под углом 60°, и хочет попасть в село [latex]NN[/latex]. Выбрав левую дорогу, он должен будет пройти [latex]n[/latex] вёрст прямо, затем повернуть направо под прямым углом и идти до [latex]NN[/latex]. Выбрав правую, он должен будет преодолеть участок некоторой длины прямо, затем повернуть налево и пройти такой же по длине участок. При этом известно, что длины левой и правой дорог одинаковы. От нас требуется найти длину пути по одной из дорог и длину пути напрямик.

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

Длина пути от развилки до N.

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

Длины путей по дороге и напрямик.

km171
Тесты.

Входные данные Выходные данные
[latex]n[/latex] [latex]{ s }_{ 1 }[/latex] [latex]{ s }_{ 2 }[/latex]
1 0 0 0
2 8 11.0416 8.55871
3 0.5 0.690101 0.534919
4 21 28.9843 22.4666
5 13.45 18.5637 14.3893

Код программы (C++).

Код программы (Java).

Решение.
Обозначим развилку как [latex]A[/latex], деревню [latex]N[/latex] как [latex]B[/latex], село [latex]NN[/latex] как [latex]C[/latex], место пересечения правой дороги с рельсами как D, и проведём [latex]DH\bot AB[/latex] и [latex]DK\bot BC[/latex]. Нам дано, что [latex]AB=n[/latex], угол [latex]BAC[/latex] — 60 градусов, [latex]AD=DC[/latex] и [latex]AB+BC=AD+CD[/latex].

Пусть [latex]AD=2x[/latex], тогда [latex]AH=x[/latex]; [latex]BH=KD=n-x[/latex]; [latex]BC=4x-n[/latex]; Из треугольника [latex]AHD[/latex]: [latex]BK=DH=x\cdot \sqrt { 3 } [/latex];

[latex]KC=KB-BC=n+x\cdot (\sqrt { 3 } -4)[/latex].
Из треугольника CKD по теореме Пифагора: [latex]{ KC }^{ 2 }+{ KD }^{ 2 }={ CD }^{ 2 }[/latex]. Подставив значения, раскрыв скобки и проведя математические преобразования, получим квадратное уравнение [latex]{ x }^{ 2 }\cdot (-4\sqrt { 3 } +8)-x\cdot n\cdot (\sqrt { 3 } -5)+{ n }^{ 2 }=0[/latex].
Найдём дискриминант [latex]D={ n }^{ 2 }\cdot (6\sqrt { 3 } -4)[/latex].

[latex]KD=n-x[/latex] и [latex]KD>0[/latex], значит, [latex]n-x>0[/latex] и [latex]x<n[/latex]. Легко доказать, что для первого из корней полученного квадратного уравнения это условие не выполняется. Значит, мы имеем лишь один корень. Найдя его, мы найдём половину длины [latex]AD[/latex]. Выведем формулу для его расчёта:
[latex]x=\frac { n\cdot (5-\sqrt { 3 } -\sqrt { 6\sqrt { 3 } -4 } ) }{ 8\cdot (2-\sqrt { 3 } ) } [/latex]
Тогда длина пути по дороге будет равна [latex]4x[/latex], а длину пути напрямик мы найдём из треугольника [latex]ABC[/latex] по теореме Пифагора: [latex]{ s }_{ 2 }=\sqrt { { 2\cdot (n }^{ 2 }-4x\cdot n+8{ n }^{ 2 }) } [/latex].

Код на ideone.com: здесь (C++) и здесь (Java).
Условие задачи (страница 27).

А58б. Нахождение значения функции

Задача. Дано действительное число [latex]a[/latex]. Для функций [latex]f\left( x \right)[/latex], графики которых представлены на рис. 1,а-1,г, вычислить [latex]f\left( a \right) [/latex].

%d0%b058%d0%b1

Тесты.

[latex]a[/latex] [latex]y[/latex]
-1 1
0 0
2 4
-2 0.25
1.6 2.56
7 4

Код программы (C++).

Код программы (Java).

Решение.
На графике функции указано, чему равна [latex]f\left( x \right)[/latex] на каждом участке. В данной программе мы по очереди проверяем, какому из них принадлежит [latex]f\left( a \right)[/latex] и выбираем соответствующую формулу для расчёта [latex]y[/latex]. Поскольку участков всего три, достаточно проверить, принадлежит ли точка к двум из них. Ели нет, то она, очевидно, лежит на третьем.

Ссылка на код на ideone.com: здесь (C++) и здесь (Java).

ML38. Максимальный размер прямоугольника, вырезанного из круга

Задача. Какого наибольшего размера прямоугольник можно вырезать из круга диаметра [latex]d[/latex], если известно, что длины его сторон образуют золотую пропорцию.

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

Единственное число — диаметр окружности.

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

Два числа — длины сторон прямоугольника.

ml38

Тесты.

Входные данные Выходные данные
[latex]d[/latex] [latex]a[/latex] [latex]b[/latex]
1 0 0 0
2 1 0.850651 0.525731
3 2 1.7013 1.05146
4 21 17.8638 11.0404
5 0.32 0.272208 0.168234
6 1.7 1.44611 0.893743
7 134 113.981 70.448

Код программы на C++.

Код программы на Java.

Решение.

Прямоугольник будет иметь наибольший размер в случае, когда его вершины лежат на окружности. Тогда, очевидно, диаметр окружности будет диагональю данного прямоугольника. Согласно условию, длины его сторон образуют золотую пропорцию. Это означает, что [latex]\frac { a }{ b } =\phi [/latex], где [latex]a[/latex] — длина большей стороны прямоугольника, [latex]b[/latex] — длина его меньшей стороны, а [latex]\phi=\frac { 1+\sqrt { 5 } }{ 2 } [/latex]. Отсюда [latex]a=b\cdot \phi[/latex]. По теореме Пифагора, [latex]{ a }^{ 2 }+{ b }^{ 2 }={ d }^{ 2 }[/latex]. Путём подстановки из предыдущего выражения и простых алгебраических преобразований получим формулу для вычисления длины меньшей стороны: [latex]b=d\cdot \sqrt { \frac { 1 }{ { \phi }^{ 2 }+1 } } [/latex].
Сначала для удобства находим значение [latex]\phi[/latex], затем — по указанным формулам длины сторон прямоугольника.

Ссылка на код на ideone.com: здесь (C++) и здесь (Java).