Матч 236, Числа Хемминга (HammingNumbers)

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

 

Числами Хемминга называются числа, простые делители которых лежат в заданном множестве. Например, если factors = {2, 3, 5}, то 90 = 2*3*3*5 является числом Хемминга, а число 70 = 2*5*7 нет, так как оно делится на 7. Число 1 всегда является первым числом Хемминга независимо от содержимого factors. Имея множество простых делителей factors, требуется найти n - ое число Хемминга. Если результат больше 2147483647, то вернуть -1.

 

Класс: HammingNumbers

Метод: int getNumber(vector<int> factors, int n)

Ограничения: factors содержит от 1 до 50 элементов, 2 £ factors[i] £ 300, 1 £ n £ 100000.

 

Вход. Массив factors, содержащий множество простых делителей числа n и само число n.

 

Выход. n - ое число Хемминга. Если результат больше 2147483647, то вернуть -1.

 

Пример входа

factors

n

{2,3,5}

15

{2,2,2,4,4,4,8,8,8}

11

{4,11,15,21,29,28}

2841

 

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

24

1024

2146636800

 

 

РЕШЕНИЕ

структуры данных + перебор

 

Будем генерировать числа Хемминга, начиная с единицы, используя структуру данных set. Занесем в нее 1. Далее совершаем n – 1 итерацию: берем наименьший элемент множества, умножаем его на все элементы массива factors и заносим полученные произведения во множество. После чего наименьший элемент удаляем. Таким образом удаляться будут числа Хемминга в возрастающем порядке пока не дойдем до очередного, n - ого числа. Если удаляемое число больше 2147483647, то можно сразу вернуть -1. Если множество на текущем шаге содержит более чем n элементов (значение n в цикле каждый раз уменьшается на 1, так что на каждой итерации n обозначает количество чисел, которое еще следует пройти), то последний элемент множества можно удалить. Это делается для того, чтобы множество не разрасталось и не было проблем с памятью. Результатом будет наименьшее значение множества. Если оно больше 2147483647, то возвращаем -1.

 

ПРОГРАММА

 

#include <cstdio>

#include <vector>

#include <set>

using namespace std;

 

set<long long> s;

 

class HammingNumbers

{

public:

  int getNumber(vector<int> factors, int n)

  {

    s.insert(1);

    while(--n)

    {

      long long x = *s.begin(); s.erase(s.begin());

      if (x > (long long)2147483647) return -1;

      for(int i = 0; i < factors.size(); i++)

      {

        s.insert(x * factors[i]);

        if (s.size() > n) s.erase(--s.end());

      }

    }

    return (*s.begin() > (long long)2147483647) ? -1 : *s.begin();

  }

};