Редактировать

ЗАДАЧА №312 Арифметическая прогрессия

(Время: 1 сек. Память: 16 Мб Сложность: 15%)

Заданы первый и второй элементы арифметической прогрессии. Требуется написать программу, которая вычислит элемент прогрессии по ее номеру.

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

Входной файл INPUT.TXT содержит три целых числа, разделенных пробелами – первый элемент прогрессии A1 (1 ≤ A1 ≤ 1000), второй элемент прогрессии A2 (1 ≤ A2 ≤ 1000), и номер требуемого элемента N (1 ≤ N ≤ 1000).

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

Выходной файл OUTPUT.TXT должен содержать одно целое число - N-й элемент арифметической прогрессии.

begin
  var (a1, a2, n) := ReadInteger3;
  Print(a1 + (a2 - a1) * (n - 1))
end.

Из курса школьной матеметики известна формула $$a_n=a_1+d(n-1),\ d=a_k-a_{k-1}=a_2-a_1 \to a_n=a_1+(a_2-a_1)(n-1)$$

Для представления данных достаточно стандартного типа integer.

ЗАДАЧА №411 Квадратное уравнение

(Время: 1 сек. Память: 16 Мб Сложность: 28%)

Сложно найти человека, который любит решать однообразные задачки по математике. В последнее время школьникам стало легче, ведь с появлением компьютеров почти в каждой квартире стало существенно проще проверять себя. Но программы, в которых решение уравнений является стандартной функцией, установлены не везде. Напишите программу, которая сможет решить уравнение ax2 + bx + c = 0 при заданных коэффициентах a, b и c.

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

Единственная строка входного файла INPUT.TXT содержит три целых числа a, b и c, каждое из которых не превосходит по модулю 30000. Числа разделяются пробелами.

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

На первой строке выходного файла OUTPUT.TXT выведите число различных действительных корней заданного уравнения. Затем выведите сами корни по одному на строке с ошибкой, не превосходящей 10-4. Если для заданных коэффициентов корней бесконечно много, на единственной строке выходного файла выведите -1.

begin
  var (a, b, c) := ReadReal3;
  if a = 0 then
    if b = 0 then
      Print(c = 0 ? -1 : 0)
    else
      Write(1, NewLine, -c / b:0:6)
  else
  begin
    var d := b * b - 4 * a * c;
    if d < 0 then
      Print(0)
    else if d = 0 then
      Write(1, NewLine, -b / (2 * a):0:6)
    else
    begin
      d := Sqrt(d);
      Write(2, NewLine, (-b - d) / (2 * a):0:6, NewLine,
          (-b + d) / (2 * a):0:6)
    end
  end
end.

Некоторую сложность этой задаче придает разветвленность алгоритма. В самом деле, при а = 0 квадратное уравнение вырождается в уравнение первой степени, а при a = b = 0 возникает вариант с = 0, где при с = 0 получается тождество 0 = 0 и х может быть любым, а при с ≠ 0 решений нет. Первая ветка алгоритма есть: если (a = 0 и b = 0), то при с = 0 вывести -1, иначе вывести 0

Уравнение первой степени имеет вид bx+c = 0, откуда х = -с/b. Случай с b = 0 здесь невозможен, он исключен предыдущей веткой и уравнение имеет единственный корень. Можно включать в алгоритм и эту ветку. если (a = 0 и b ≠ 0), то вывести 1 и в следующей строке значение -c/b

Осталось рассмотреть случай a ≠ 0, приводящий к квадратному уравнению. Алгоритм решения квадратного урвнения школьникам известен. Сначала вычисляется дискриминант D = b2 - 4ac. Далее возможны три случая. При D < 0 действительных корней нет и выводим 0 (вот оно - коварство этого задания - корней нет, значит их ноль). При D = 0 имеются два совпадающих корня (“корни действительные и равные”), но в задаче требуется вывести число различных действительных корней, поэтому тут выводим 1 и значение одного корня, равное -b / 2a.

Наконец, при D > 0 уравнение имеет два действительных и различных корня. Здесь выводим 2 и значения корней, полученные по формуле $$x_{1,2}=\frac{-b\pm\sqrt{D}}{2a}$$

Исходные данные представляем в стандартном типе real

ЗАДАЧА №682 Сумма n-значных чисел

(Время: 1 сек. Память: 16 Мб Сложность: 30%)

По заданному n найти сумму всех n-значных чисел.

Входные данные В единственной строке входного файла INPUT.TXT записано одно натуральное число n (1 ≤ n ≤ 100).

Выходные данные В единственную строку выходного файла OUTPUT.TXT нужно вывести все цифры суммы всех n-значных чисел.

begin
  var n := ReadInteger;
  var k := Biginteger(10) ** (n - 1);
  Print(9 * k * (11 * k - 1) div 2)
end.

Задача на нахождение суммы арифметической прогрессии $$S=\frac{a_1+a_n}{2}n$$

Сложность в том, что эта сумма может оказаться очень большой для n-значных чисел.

Например, если n=100, то нужно найти значение $$S=\frac{10^{99}+(10^{100}-1)}{2}9\cdot10^{99}$$

Это число, запись которого содержит около 200 цифр, так что понадобится тип BigInteger.

Приведем формулу к виду, минимизирующему количество возведений в степень. $$S=\frac{10^{n-1}+10^n-1}{2}9\cdot10^{n-1}; \ k=10^{n-1} \to S=\frac{k+10k-1}{2}9k=\frac{9k(11k-1)}{2}$$

При написании программы на время такой подход оптимален. Если хочется решить задачу “красивее” и создать программу, позволяющую получать суммы для n = 1000, 10000 и т.д. придется заняться анализом получаемых сумм. С этой целью получим суммы для n = 1..5.

n = 1 S=45

n = 2 S=4905

n = 3 S=494550

n = 4 S=49495500

n = 5 S=4949955000

Начиная с n = 3 просматривается закономерность: сначала идет ‘494’, потом n-3 раза повторяется ‘9’, далее следует ‘55’, и в конце n-2 раза повторяется ‘0’. Это позволяет написать вариант программы, обходящийся без BigInteger.

begin
  var n := ReadInteger;
  case n of
    1: Print('45');
    2: Print('4905');
  else
    Print('494' + (n - 3) * '9' + '55' + (n - 2) * '0')
  end
end.

ЗАДАЧА №205 Таймер

(Время: 1 сек. Память: 16 Мб Сложность: 31%)

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

Входные данные В первой строке входного файла INPUT.TXT записано текущее время в формате ЧЧ:ММ:СС (с ведущими нулями). При этом оно удовлетворяет ограничениям: ЧЧ - от 00 до 23, ММ и СС - от 00 до 60.

Во второй строке записан интервал времени, который должен быть измерен. Интервал записывается в формате Ч:М:С (где Ч, М и С - от 0 до 109, без ведущих нулей). Дополнительно если Ч=0 (или Ч=0 и М=0), то они могут быть опущены. Например, 100:60 на самом деле означает 100 минут 60 секунд, что то же самое, что 101:0 или 1:41:0. А 42 обозначает 42 секунды. 100:100:100 - 100 часов, 100 минут, 100 секунд, что то же самое, что 101:41:40.

Выходные данные В выходной файл OUTPUT.TXT выведите в формате ЧЧ:ММ:СС время, во сколько прозвучит звуковой сигнал. При этом если сигнал прозвучит не в текущие сутки, то дальше должна следовать запись +”количество” days. Например, если сигнал прозвучит на следующий день – то +1 days.

begin
  var k: array of int64 = (1, 60, 3600);
  var a := ReadlnString.Replace(':', ' ').ToIntegers;
  var t := a[0] * k[2] + a[1] * k[1] + a[2];
  a := ReadlnString.Replace(':', ' ').ToIntegers;
  Reverse(a);
  for var i := 0 to a.High do
    t += a[i] * k[i];
  var s := $':{t mod 60:d2}';
  t := t div 60;
  s := $':{t mod 60:d2}' + s;
  t := t div 60;
  s := $'{t mod 24:d2}' + s;
  t := t div 24;
  if t > 0 then
    s += $'+{t} days';
  s.Print
end.

Идея решения проста: вести расчеты в секундах. В одном часе 3600 секунд, в одной минуте - 60. К исходному времени добавляется временной интервал, а итог из секунд переводится в дни, часы, минуты и секунды. Гораздо большую проблему может представлять интерпретация исходных данных из-за нестандартного разделителя “:” и достаточно вольной записи временного интервала. При формировании вывода удобно использовать интерполированные строки.