Разбор решения
Дано число s — до 10⁶ цифр.
Найти 1 ≤ l ≤ r ≤ 3·10⁵, такие что
s = 120 → 4 · 5 · 6 = 120
Подойдёт любой верный ответ, например и 1 · 2 · 3 · 4 · 5.
→ Будем для каждого l находить подходящий r.
pref[i] = 1 · 2 · … · i
Пример: 4·5·6 = 720 / 6 = 120
Перебор пар исчез: один проход по l.
pref[300000] = 300000! — 1 512 852 цифры
Если A = B, то A % p = B % p. При большом простом p обратное почти всегда тоже верно.
s = 120 по модулю 7, по цифрам:
1 → 1
1·10 + 2 = 12 → 5
5·10 + 0 = 50 → 1
4·5·6 по модулю 7:
4 → 4
4·5 = 20 → 6
6·6 = 36 → 1
Всё решение то же самое, только s и pref хранятся по модулю p — обычными числами, и они остаются меньше p.
Где взять большое простое
• Запомнить готовые: 10⁹+7, 998244353, 10¹⁸+9
• Числа вида 2ⁿ − 1 (числа Мерсенна) иногда простые: 2³¹ − 1 и 2⁶¹ − 1 — простые
Но не при любом n: 2¹¹ − 1 = 2047 = 23 · 89. Простым оно может быть, только если n простое.
const long long MOD = 1000000000000000009LL; // простое около 10^18 long long mul(long long a, long long b) { return (__int128)a * b % MOD; } long long h = 0; // остаток s for (char c : s) h = (mul(h, 10) + (c - '0')) % MOD; pref[0] = 1; // префиксные произведения for (int i = 1; i <= MAXR; i++) pref[i] = mul(pref[i - 1], i); unordered_map<long long, int> whereR; // значение pref[r] -> r for (int r = 1; r <= MAXR; r++) whereR[pref[r]] = r; for (int l = 1; l <= MAXR; l++) { // pref[r] = s * pref[l-1] auto it = whereR.find(mul(h, pref[l - 1])); if (it != whereR.end() && it->second >= l) { cout << l << " " << it->second; return 0; } }
Сложность: O(|s| + R), где R = 3·10⁵