10378. Непредставимые

 

Задано натуральное число n. Сколько чисел от 1 до n (включительно) непредставимы в виде ab, где a и b – натуральные числа, не менее 2?

 

Вход. Одно натуральное число n (1 ≤ n ≤ 1010).

 

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

 

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

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

8

6

 

 

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

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

100000

99634

 

 

РЕШЕНИЕ

структуры данных - set

 

Анализ алгоритма

Количество непредставимых чисел равно

n – количество чисел, представимых в виде ab

Найдем все числа, представимые в виде ab, где a > 1, b > 1, abn. Таких чисел немного, так что их всех можно сгенерировать и сохранить в контейнер. Степени будут повторяться, например 212, 46 и 163. Повторы чисел следует удалять, поэтому в качестве контейнера выберем множество set.

Будем генерировать степени ab, где a = 2, 3, 4, …,  . Для каждого значения a перебираем b = 2, 3, 4, … пока степень не больше n. Например:

·        степени двойки 22, 23, 24, … n;

·        степени тройки 32, 33, 34, … n;

·        степени четверки 42, 43, 44, … n;

 

Пример

На промежутке [1; 8] имеются два числа представимые в виде степеней: 22 = 4 и 23 = 8. Таким образом непредставимых будет 8 – 2 = 6 чисел.

Пусть n = 50. Тогда будут сгенерированы следующие степени:

·        22 = 4, 23 = 8, 24 = 16, 25 = 32 (26 = 64 > 50);

·        32 = 9, 33 = 27 (34 = 81 > 50);

·        42 = 16 (43 = 64 > 50);

·        52 = 25 (53 = 125 > 50);

·        62 = 36 (63 = 216 > 50);

·        72 = 49 (73 = 343 > 50);

Заметим, что 24 = 16 и 42 = 16, однако во множестве дубли удалятся. Для n = 50 множество s будет иметь вид: {4, 8, 9, 16, 25, 27, 32, 36, 49}. Количество непредставимых чисел на промежутке [1; 50] равно 50 – s.size() = 50 – 9 = 41.

 

Реализация алгоритма

Объявим множество s.

 

#define ll long long

set<ll> s;

 

Читаем входное значение n.

 

scanf("%lld", &n);

 

Перебираем основание степени a.

 

for (a = 2; a * a <= n; a++)

{

 

Инициализируем x = a2. Далее в переменной x перебираем степени числа a: a3, a4, … . Заносим сгенерированные степени во множество s.

 

  ll x = a * a;

  while (x <= n)

  {

    s.insert(x);

    x *= a;

  }

}

 

Значение s.size() содержит количество чисел, представимых в виде ab. Выводим ответ, равный ns.size().

 

printf("%lld\n", n - s.size());

 

Java реализация

 

import java.util.*;

 

class Main

{

  public static void main(String[] args)

  {

    Scanner con = new Scanner(System.in);

    TreeSet<Long> s = new TreeSet<Long>();

    long n = con.nextLong();

   

    for (long a = 2; a * a <= n; a++)

    {

      long x = a * a;

      while (x <= n)

      {

        s.add(x);

        x *= a;

      }

    }

    System.out.print(n - s.size());

    con.close();

  }

}