Матч 431, Сумма и произведение (SumAndProduct)

Дивизион 2, Уровень 3

 

Список неотрицательных чисел называется удовлетворительным, если их сумма равна s, а произведение p. Найти удовлетворительный список с наименьшим количеством элементов и вернуть его длину. Если такого списка не существует, вернуть -1.

 

Класс: SumAndProduct

Метод: int smallestSet(int s, int p)

Ограничения: 1 £ s, p £ 109.

 

Вход. Два числа s и p.

 

Выход. Наименьшее количество элементов в удовлетворительном списке. Если такого списка не существует, вернуть -1.

 

Пример входа

s

p

10

10

5

100

100

1000000000

 

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

1

-1

9

 

 

РЕШЕНИЕ

математика

 

В задаче следует найти наименьшее n, для которого существуют такие x1, x2, …, xn, что

Рассмотрим, какие значения может принимать произведение x1 * x2 * … * xn для заданных n и s. Если n = 1, то решением будет x1 = s = p. При n = 2 сумма x1 + x2 = s, произведение равно x1 * x2 = x1 * (sx1). Рассмотрим, какие значения может принимать произведение. Решим уравнение x * (sx) = p или x2s * x + p = 0. Дискриминант уравнения равен D = s2 – 4 * p. Уравнение имеет решение при D ³ 0 или p £ s2 / 4 . Если p ³ 0, то решения

x1,2 =

будут неотрицательными. Таким образом, с помощью двух действительных чисел, сумма которых равна s, можно получить любое произведение от 0 до s2 / 4. При этом наибольше произведение s2 / 4 можно получить при x1 = x2 = s / 2.

 

Лемма. Если сумма n чисел равна s, то их максимально произведение равно (s / n)n и достигается при x1 = x2 = … = xn = s / n.

Если предположить противное, то найдется наименьшее m = xi и наибольшее M = xj среди этих чисел. Заменим m и M на числа (m + M) / 2 и (m + M) / 2. В таком случае произведение x1 * x2 * … * xn увеличится.

Доказательство. Докажем неравенство . Имеем: , , что верно так как по предположению m и M не равны между собой.

 

Теорема. Если сумма n чисел равна s, то их произведение может принимать любое значение от 0 до (s / n)n.

Согласно лемме, наибольшее значение (s / n)n достигается при x1 = x2 = … = xn = s / n. Осталось показать, что достигается и любое другое произведение p, 0 £ p £ (s / n)n. Доказательство проведем конструктивно.

Возьмем b = p / (s / n)n-2. Очевидно, что 0 £ b £ (s / n)2. Исходя из выше доказанного, существуют такие x1 и x2, что x1 + x2 = 2 * s / n, x1 * x2 = b £ (2 * s / n)2 / 4 = (s / n)2. Добавим значения x3 = x4 = … = xn = s / n чтобы получить требуемые n чисел: x1 + x2 + … + xn = 2 * s / n + (n – 2) * s / n = s, x1 * x2 * … * xn = b * (s / n)n-2 = p.

 

Таким образом, алгоритм решения задачи состоит в следующем:

1. Если s = p, то вернуть 1.

2. Последовательно перебираем n = 2, 3, …, s. Как только станет p £ (s / n)n, возвращаем n.

3. Если на втором шаге решение не найдено, то возвращаем -1.

 

Пример. Найти n = 5 чисел, сумма которых равна s = 10, а произведение p = 30.

Такие числа существуют, так как p (s / n)n = (10 / 5)5 = 32. Выберем такие x1 и x2, что x1 + x2 = 2 * s / n = 2 * 10 / 5 = 4, а их произведение равно b = p / (s / n)n-2 = 30 / (10 / 5)3 = 30 / 8 = 15 / 4. Такие числа существуют согласно лемме. Выберем x3 = x4 = x5 = s / n = 10 / 5 = 2. Указанные пять чисел и будут являться ответом.

 

ПРОГРАММА

 

#include <stdio.h>

#include <math.h>

 

class SumAndProduct

{

public:

  int smallestSet(int s, int p)

  {

    int n;

    if (s == p) return 1;

    for(n = 2; n <= s; n++)

      if (pow(1.0 * s / n, 1.0 * n) >= p) return n;

    return -1;

  }

};