Новая Школа - онлайн-школа подготовки к ЕГЭ
Задача Задача №3315202
А
Аноним
23 августа 2025 17:41 · публичный вопрос
А
Аноним

Недавно у одного известного исполнителя появилась новая песня. Он хочет загрузить её в VK Музыку. Перед пиар-менеджером встала задача — выбрать длительность в секундах для трека,…

Запрос пользователя

Недавно у одного известного исполнителя появилась новая песня. Он хочет загрузить её в VK Музыку. Перед пиар-менеджером встала задача — выбрать длительность в секундах для трека, который в итоге будет представлен в VK Музыке. В оригинале песня длится t секунд. Можно изменить её не более чем на d секунд, при это длительность песни должна являться натуральным числом. И главное, поскольку это число должно быть красивым, то длительность также должна иметь не более трёх делителей. Посчитайте количество способов выбрать длительность трека, с учётом двух перечисленных выше условий. Система оценки Группа тестов Дополнительные ограничения Баллы Необходимые группы 1 t≤106,d≤104 10 — 2 t≤109,d≤105 35 1 3 t≤2⋅107,d≤5⋅106 30 1 4 t≤5⋅1013,d≤5⋅106 25 1−3 Формат входных данных В единственной строке содержатся два целых числа, разделённых пробелом t и d. (1≤t≤5⋅1013, 1≤d≤5⋅106). Формат выходных данных Выведите одно целое число - количество способов выбрать длительность трека. напиши код на джава или питоне

Ответ нейросети
23 августа 2025 17:41

Задача сводится к таким числам: числа с не более чем 3 делителями это 1, простые числа и квадраты простых чисел. Нужно посчитать, сколько таких чисел лежит в диапазоне [L, R], где L = max(1, t − d), R = t + d.

Чтобы посчитать в диапазоне до 1e7 элементов количество простых чисел и квадратов простых, удобно использовать сегментированный решет. Нужно:

  • Найти все простые числа до sqrt(R) (потому что чтобы проверить простой в диапазоне [L, R], достаточно делителей до sqrt(R)).
  • Применить сегментированный решет по диапазону [L, R], пометив составные числа.
  • Посчитать количество простых в диапазоне.
  • Посчитать количество квадратов простых p^2 в диапазоне, перебрав простые p до sqrt(R) и считав те, чьи квадраты попадают в [L, R].
  • Учесть число 1, если оно попадает в диапазон.

Код на Java:

import java.io.*;
import java.util.*;

/*
  Решение: подсчитываем числа с не более чем 3 делителями в диапазоне [L, R],
  где L = max(1, t - d), R = t + d.
  Такие числа: 1, primes, и p^2 (поскольку d(n) = 3 для n = p^2, p - простое).
*/
public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String line = br.readLine();
        if (line == null || line.trim().isEmpty()) return;
        StringTokenizer st = new StringTokenizer(line);
        long t = Long.parseLong(st.nextToken());
        long d = Long.parseLong(st.nextToken());

        long L = t - d;
        if (L < 1) L = 1;
        long R = t + d;

        int limit = (int) Math.floor(Math.sqrt((double) R)); // sqrt(R)

        // Сначала находим все простые до limit
        boolean[] isPrimeSmall = new boolean[limit + 1];
        Arrays.fill(isPrimeSmall, true);
        if (limit >= 0) isPrimeSmall[0] = false;
        if (limit >= 1) isPrimeSmall[1] = false;
        for (int i = 2; (long) i * i <= limit; i++) {
            if (isPrimeSmall[i]) {
                for (int j = i * i; j <= limit; j += i) isPrimeSmall[j] = false;
            }
        }
        ArrayList<Integer> primes = new ArrayList<>();
        for (int i = 2; i <= limit; i++) {
            if (isPrimeSmall[i]) primes.add(i);
        }

        // Сегментированное решето для [L, R]
        int len = (int) (R - L + 1);
        boolean[] segPrime = new boolean[len];
        Arrays.fill(segPrime, true);

        for (int p : primes) {
            long lp = p;
            long start = Math.max(lp * lp, ((L + p - 1) / p) * lp);
            if (start > R) continue;
            for (long x = start; x <= R; x += lp) {
                segPrime[(int) (x - L)] = false;
            }
        }

        // Момент: 1 не является простым
        if (L == 1) segPrime[0] = false;

        long countPrimesInSegment = 0;
        for (int i = 0; i < len; i++) {
            if (segPrime[i]) {
                long val = L + i;
                if (val >= 2) countPrimesInSegment++;
            }
        }

        // Подсчет чисел p^2 внутри [L, R], где p — простое
        long countPrimeSquares = 0;
        for (int p : primes) {
            long sq = (long) p * p;
            if (sq > R) break;
            if (sq >= L) countPrimeSquares++;
        }

        // Учет числа 1, если оно в диапазоне
        long total = 0;
        if (L <= 1 && 1 <= R) total += 1;
        total += countPrimesInSegment;
        total += countPrimeSquares;

        System.out.println(total);
    }
}

Пояснения по сложности:

  • Построение простых до sqrt(R): O(limit log log limit), limit ≈ 7.1e6.
  • Сегментированное sieve на диапазон длины до 2d+1 ≤ 1e7: около O(range log log limit) операций.
  • Подсчет квадратов простых до sqrt(R): до порядка количества primes до sqrt(R) (~ 4–5 сотен тысяч), что быстро.

Этот подход подходит для условий задачи: t ≤ 5·10^13, d ≤ 5·10^6.