ЕГЭ по информатике 2027 на C++: задания 24–27 с разбором

Что известно о ЕГЭ по информатике 2027 и как решать на C++ четыре задания на программирование: 24 (строки), 25 (делители и маски), 26 (сортировка) и 27 (кластеры). Учебные задачи того же типа с готовыми решениями и типичными ошибками.

Содержание

ЕГЭ по информатике сдают за компьютером, и последние четыре задания — 24, 25, 26 и 27 — обычно решают программой. Язык можно выбрать любой из установленных в пункте проведения экзамена. C++ среди них есть почти всегда: он быстрый, и для заданий с большими файлами это заметное преимущество.

В статье — что известно об экзамене 2027 года и по одной учебной задаче на каждое из четырёх заданий с решением на C++. Задачи составлены нами по образцу экзаменационных, а все программы проверены на сгенерированных данных.

Что известно о ЕГЭ-2027

На момент написания статьи (октябрь 2026 года) ФИПИ опубликовал демоверсию, спецификацию и кодификатор 2027 года в виде проектов: замечания к ним принимались до 30 сентября. Окончательные документы могут отличаться, поэтому сверяйтесь с сайтом ФИПИ.

Что следует из проекта и сообщений Рособрнадзора:

  • структура экзамена сохраняется: 27 заданий, 3 часа 55 минут, максимум 29 первичных баллов;
  • задания 26 и 27 оцениваются в 2 балла, остальные — в 1;
  • тематика трёх заданий изменена — каких именно и как, смотрите в спецификации;
  • в задании 27 упрощена запись ответа: одна строка из двух чисел;
  • файлы к заданиям 17, 24, 26 и 27 — текстовые, в формате .txt.

Общая заготовка: чтение файла

В заданиях 24, 26 и 27 данные лежат в файле. Положите его в папку с программой и читайте через std::ifstream — точно так же, как через std::cin:

C++
#include <fstream>
#include <iostream>

int main() {
    std::ifstream file("24.txt");
    if (!file) {
        std::cout << "Файл не открылся\n";
        return 1;
    }
    // дальше: file >> значение;
}

Проверка if (!file) экономит минуты: если файл назван иначе или лежит в другой папке, программа скажет об этом сразу, а не выведет ноль.

Задание 24. Обработка строки

Тип. В файле — одна длинная строка. Нужно найти самую длинную цепочку символов с заданным свойством.

Учебная задача. Файл 24.txt содержит строку из букв A, B и C длиной до миллиона символов. Найдите длину самой длинной цепочки, в которой никакие две соседние буквы не совпадают.

Идея. Идём по строке один раз и держим длину текущей подходящей цепочки. Если буква совпала с предыдущей, цепочка обрывается и начинается заново с этой буквы.

C++
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>

int main() {
    std::ifstream file("24.txt");
    std::string s;
    file >> s;

    int best = 0;
    int current = 0;
    for (std::size_t i = 0; i < s.size(); ++i) {
        if (i > 0 && s[i] == s[i - 1]) {
            current = 1;            // цепочка оборвалась: начинаем новую с текущей буквы
        } else {
            ++current;
        }
        best = std::max(best, current);
    }
    std::cout << best << '\n';
    return 0;
}

Где ошибаются.

  • Сбрасывают счётчик в 0, а не в 1: буква, на которой цепочка оборвалась, сама начинает новую.
  • Обновляют ответ только при обрыве цепочки и теряют ту, что дошла до конца строки.
  • Пишут два вложенных цикла «для каждого начала ищем конец». Для строки в миллион символов это не успеет: нужен один проход.

Задание 25. Делители и маски

Тип. Перебор чисел с проверкой свойства: количество делителей, простота, соответствие маске. Файла нет, программа сама перебирает числа.

Учебная задача. Среди чисел от 800 000 до 800 100 найдите те, у которых ровно четыре различных натуральных делителя. Для каждого выведите само число и его наибольший делитель, не равный самому числу.

Идея. Делители идут парами: если d делит n, то и n / d делит n. Поэтому достаточно перебирать d до корня из n.

C++
#include <iostream>
#include <vector>

int main() {
    for (long long n = 800000; n <= 800100; ++n) {
        std::vector<long long> divisors;
        for (long long d = 1; d * d <= n; ++d) {
            if (n % d == 0) {
                divisors.push_back(d);
                if (d != n / d) divisors.push_back(n / d);
            }
            if (divisors.size() > 4) break;     // делителей уже слишком много
        }
        if (divisors.size() == 4) {
            long long largest = 0;
            for (long long d : divisors) {
                if (d != n && d > largest) largest = d;
            }
            std::cout << n << ' ' << largest << '\n';
        }
    }
    return 0;
}

Программа выводит 21 строку, первые три: 800003 47059, 800005 160001, 800013 266671.

Маски. В другом варианте задания числа должны подходить под маску, где ? — одна любая цифра, а * — любая последовательность цифр, в том числе пустая. Например: найти числа, не превышающие 10^9, которые подходят под маску 12*4?5 и делятся на 2027.

Здесь важны две вещи. Первая: перебирать нужно не все числа, а только кратные 2027, с шагом 2027 — это в две тысячи раз быстрее. Вторая: проверку маски удобно написать отдельной функцией.

C++
#include <iostream>
#include <string>

// Подходит ли число (в виде строки) под маску: ? — одна любая цифра, * — любая последовательность цифр.
bool matches(const std::string& mask, const std::string& number, std::size_t i = 0, std::size_t j = 0) {
    if (i == mask.size()) return j == number.size();
    if (mask[i] == '*') {
        for (std::size_t k = j; k <= number.size(); ++k) {
            if (matches(mask, number, i + 1, k)) return true;
        }
        return false;
    }
    if (j == number.size()) return false;
    if (mask[i] == '?' || mask[i] == number[j]) return matches(mask, number, i + 1, j + 1);
    return false;
}

int main() {
    const std::string mask = "12*4?5";
    for (long long n = 2027; n <= 1000000000; n += 2027) {      // только числа, кратные 2027
        if (matches(mask, std::to_string(n))) {
            std::cout << n << ' ' << n / 2027 << '\n';
        }
    }
    return 0;
}

Первые строки вывода: 12192405 6015, 12273485 6055, 12496455 6165.

Где ошибаются.

  • Перебирают делители до n, а не до корня: для чисел порядка 10^9 это не успеет.
  • Забывают, что у точного квадрата парные делители совпадают, и считают один делитель дважды.
  • Используют int там, где произведение или само число выходит за два миллиарда.

Задание 26. Сортировка

Тип. В файле — набор чисел или записей. Решение почти всегда начинается с сортировки, после которой ответ находится одним проходом.

Учебная задача. В первой строке файла 26.txt записаны объём диска S и количество файлов N, далее — N чисел, размеры файлов. Нужно сохранить на диск как можно больше файлов. Выведите наибольшее количество файлов и наибольший возможный размер самого большого файла среди всех способов сохранить столько файлов.

Идея. Чтобы файлов было больше, берём самые маленькие. Потом пробуем улучшить второй ответ: последний взятый файл заменяем на более крупный, пока он помещается в освободившееся место.

C++
#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>

int main() {
    std::ifstream file("26.txt");
    long long capacity;
    int n;
    file >> capacity >> n;
    std::vector<long long> sizes(n);
    for (long long& size : sizes) file >> size;

    std::sort(sizes.begin(), sizes.end());

    // Берём самые маленькие файлы, пока они помещаются.
    long long used = 0;
    int count = 0;
    while (count < n && used + sizes[count] <= capacity) {
        used += sizes[count];
        ++count;
    }

    // Пробуем заменить последний взятый файл на самый большой из подходящих.
    long long largest = count > 0 ? sizes[count - 1] : 0;
    if (count > 0) {
        long long room = capacity - used + sizes[count - 1];
        for (int i = count; i < n && sizes[i] <= room; ++i) {
            largest = sizes[i];
        }
    }
    std::cout << count << ' ' << largest << '\n';
    return 0;
}

Где ошибаются.

  • Отвечают на первый вопрос и забывают про второй: ответ состоит из двух чисел, и для полного балла верными должны быть оба.
  • Считают суммы в int: при больших размерах и тысячах файлов сумма переполняется.
  • Проверяют решение только на примере из условия. Сделайте файл из пяти-шести чисел, для которого ответ можно посчитать вручную.

Задание 27. Кластеры

Тип. В файле — координаты точек на плоскости. Точки образуют несколько групп — кластеров. Для каждого кластера нужно найти центр — точку кластера, сумма расстояний от которой до остальных его точек наименьшая, — и по центрам вычислить два числа.

Учебная задача. В файле 27.txt в каждой строке записаны координаты точки: x и y. Точки образуют три кластера; расстояние между точками разных кластеров больше 1, а внутри кластера от любой точки можно дойти до любой другой шагами короче 1. Найдите центры кластеров. Выведите два числа: целую часть среднего арифметического абсцисс центров, умноженного на 10 000, и то же для ординат.

Идея. Решение состоит из трёх шагов.

  1. Прочитать точки. В файле дробная часть может быть отделена запятой — заменяем её на точку.
  2. Разбить точки на кластеры: от неразмеченной точки «заражаем» всех, кто ближе порога, потом их соседей и так далее.
  3. В каждом кластере перебрать все точки и для каждой посчитать сумму расстояний до остальных.
C++
#include <algorithm>
#include <cmath>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>

struct Point {
    double x, y;
};

double distance(const Point& a, const Point& b) {
    return std::hypot(a.x - b.x, a.y - b.y);
}

int main() {
    std::ifstream file("27.txt");
    std::vector<Point> points;
    std::string sx, sy;
    while (file >> sx >> sy) {
        std::replace(sx.begin(), sx.end(), ',', '.');     // в файле может стоять десятичная запятая
        std::replace(sy.begin(), sy.end(), ',', '.');
        points.push_back({std::stod(sx), std::stod(sy)});
    }

    const double gap = 1.0;       // точки одного кластера ближе друг к другу, чем gap
    const int n = points.size();
    std::vector<int> cluster(n, -1);
    int clusters = 0;

    // Разбиение на кластеры: обход «соседей» от каждой ещё не размеченной точки.
    for (int start = 0; start < n; ++start) {
        if (cluster[start] != -1) continue;
        std::vector<int> queue = {start};
        cluster[start] = clusters;
        for (std::size_t head = 0; head < queue.size(); ++head) {
            int current = queue[head];
            for (int other = 0; other < n; ++other) {
                if (cluster[other] == -1 && distance(points[current], points[other]) < gap) {
                    cluster[other] = clusters;
                    queue.push_back(other);
                }
            }
        }
        ++clusters;
    }

    // Центр кластера — точка с наименьшей суммой расстояний до остальных его точек.
    double sum_x = 0, sum_y = 0;
    for (int c = 0; c < clusters; ++c) {
        int center = -1;
        double best = 0;
        for (int i = 0; i < n; ++i) {
            if (cluster[i] != c) continue;
            double total = 0;
            for (int j = 0; j < n; ++j) {
                if (cluster[j] == c) total += distance(points[i], points[j]);
            }
            if (center == -1 || total < best) {
                best = total;
                center = i;
            }
        }
        sum_x += points[center].x;
        sum_y += points[center].y;
    }

    long long px = static_cast<long long>(std::fabs(sum_x / clusters) * 10000);
    long long py = static_cast<long long>(std::fabs(sum_y / clusters) * 10000);
    std::cout << px << ' ' << py << '\n';
    return 0;
}

Оба вложенных перебора делают порядка N^2 действий. Для десяти тысяч точек это сто миллионов вычислений расстояния — программа на C++ справляется за секунды, и ускорять её не нужно.

Где ошибаются.

  • Не замечают десятичную запятую: file >> x для вещественного числа читает 2,5 как 2 и ломает всё дальнейшее чтение.
  • Подбирают порог gap наугад. Сначала посмотрите на точки — откройте файл в электронной таблице и постройте диаграмму: по ней видно и число кластеров, и расстояние между ними.
  • Выводят число кластеров, не проверив его. Добавьте отладочную строку std::cout << clusters: если получилось не столько, сколько в условии, порог выбран неверно.
  • Округляют вместо того, чтобы взять целую часть.

Как распределить время

На экзамен отводится 235 минут. Задания 24–27 требуют написать и отладить программу, поэтому оставляйте на них не меньше полутора часов. Разумный порядок: 24 и 25 — они короче; затем 26; затем 27.

Несколько правил, которые экономят баллы.

  • Проверяйте на маленьком примере. Сделайте файл из пяти строк, ответ для которого посчитан вручную.
  • Берите long long для сумм и произведений.
  • Не оптимизируйте заранее. Простое решение за N^2 для десяти тысяч чисел проходит; сложное решение с ошибкой — нет.
  • Сохраняйте программу перед каждым запуском и ответ — сразу, как получили.

С чего начать подготовку

Задания 24–27 проверяют не знание C++, а умение быстро и без ошибок писать простые программы: циклы, массивы, строки, сортировку. Если эти темы пока даются с трудом, начните с них:

Источники

  1. Демоверсии, спецификации, кодификаторы ЕГЭ — ФИПИ [Электронный ресурс]. — URL: https://fipi.ru/ege/demoversii-specifikacii-kodifikatory (дата обращения: 10.10.2026).
  2. Рособрнадзор сообщил об изменениях в ОГЭ и ЕГЭ в 2027 году — Эксперт [Электронный ресурс]. — URL: https://expert.ru/news/rosobrnadzor-soobschil-ob-izmeneniyakh-v-oge-i-ege-v-2027-godu (дата обращения: 10.10.2026).
  3. std::basic_ifstream — cppreference.com [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/io/basic_ifstream (дата обращения: 10.10.2026).
  4. std::sort — cppreference.com [Электронный ресурс]. — URL: https://en.cppreference.com/w/cpp/algorithm/sort (дата обращения: 10.10.2026).
C++ЕГЭИнформатика