#include <iostream> #include <vector> using namesp...
Erstellt am: 24. Oktober 2025
Beantwortet mit GPT-5 Thinking von Chat01
Erstellt am: 24. Oktober 2025
Beantwortet mit GPT-5 Thinking von Chat01
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n = 0;
cin >> n;
textint* a = new int[n]; vector<int> p(n+1); p[0] = 0; int ibest = 0; int jbest = 0; int imin = 0; bool find = false; for (int i = 1; i <= n; ++i) { cin >> a[i-1]; p[i] = p[i-1] + a[i-1]; } for (int j = 1; j <= n; ++j) { if (p[j] % 3 == 0) { ibest = 0; find = true; jbest = j; } } if (find) cout << ibest + 1 << " " << jbest<< endl; else cout << -1;
}
алгоритм должен быть линейным, дай мне маленькие подсказки как решить задачу НЕ ПИШИ КОД
Короткие подсказки (без кода):
Подумай про префикс-суммы по модулю 3.
Сумма на отрезке (i+1…j) делится на 3 ⇔ p[j] ≡ p[i] (mod 3).
Достаточно держать самые ранние индексы появления каждого остатка r∈{0,1,2} у p[k].
Инициализация: «ранний» индекс для r=0 равен 0 (пустой префикс), для остальных — «не задан».
Идёшь один раз слева направо. На позиции j считаешь r = p[j] mod 3 (аккуратно нормализуй в {0,1,2}, если суммы могут быть отрицательными).
Если лучший найденный отрезок имеет длину ≥1 — выведи (start+1, end) в 1-индексации. Иначе выведи −1.
(Осторожно с off-by-one: начало = earliest[r]+1, конец = j.)
Типы: префикс-сумму держи в 64-битном (например, long long), т.к. сумма может быть порядка 1e14.
Почему твой текущий подход не работает: он учитывает только префиксы с p[j] % 3 == 0 (отрезки, начинающиеся с 1-го элемента). Нужно сравнивать равные остатки префиксов, чтобы ловить отрезки с произвольным началом.
С этим получится линейный алгоритм O(N) и O(1) памяти.
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main()
{
int n = 0;
cin >> n;
textint* a = new int[n]; vector<int> p(n+1); p[0] = 0; int ibest = 0; int jbest = 0; int imin = 0; bool find = false; vector<int> index(3); index[0] = 0; index[1] = -1; index[2] = -1; int maxlen = 0; for (int i = 1; i <= n; ++i) { cin >> a[i-1]; p[i] = p[i-1] + a[i-1]; if ((fabs(p[i] % 3) == 1) && index[1] == -1) { index[1] = i; //cout << "dgfg0 " << index[1] << endl; } else if ((fabs(p[i] % 3) == 2) && index[2] == -1) { index[2] = i; //cout << "dgfg0adgafg " << index[2] << endl; } if ((i - index[fabs(p[i] % 3)] > maxlen) && index[fabs(p[i] % 3)] != -1) { maxlen = i - index[fabs(p[i] % 3)]; ibest = index[fabs(p[i] % 3)]; jbest = i; find = true; } } if (find) cout << ibest + 1<< " " << jbest << endl; else cout << -1;
}
я изменл алгоритм, дай ещё слабые подскаазки
круто, ты почти у цели! ещё несколько “слабых” подсказок без кода:
не используй fabs и вообще abs для остатков. Нормализуй так: r = ((sum % 3) + 3) % 3 → гарантированно r ∈ {0,1,2} даже при отрицательных суммах. Сейчас fabs(p[i] % 3) смешивает остатки 1 и -1 (а -1 по модулю 3 — это 2).
префикс-сумма должна быть 64-битной (например, long long), иначе переполнение: N ≤ 1e5, |a[i]| ≤ 1e9 → сумма до 1e14.
массив a и вектор p не нужны — достаточно идти слева направо, поддерживая текущую сумму (или сразу остаток) и три “самых ранних” индекса для остатков 0,1,2.
индексы первых появлений остатков:
earliest[0] = 0, earliest[1] = earliest[2] = -1.
Обновляй earliest[r] только при первом появлении остатка r.
кандидат на ответ на шаге i: отрезок (earliest[r] + 1 … i), где r — текущий остаток.
сравнение кандидатов: сначала по длине, а при равной длине бери тот, у которого начало меньше (earliest[r] минимален). Это соответствует условию задачи.
off-by-one: печатай (start = earliest[r] + 1, end = i) в 1-индексации.
мелочь: если за весь проход ни разу не обновил лучший отрезок, выводи -1.
если поправишь нормализацию остатка и тип суммы — решение станет корректным и линейным.