Автор задачі: | Mohammad Nasser (MOAGEZA) |
Підготував: | Mohammad Nasser (MOAGEZA) |
Редактор: | Hasan Saleh (MathModel) |
Розв'язок
Загальна ідея: Спочатку попередньо обчисліть усі прості числа до 10^7 за допомогою решета Ератосфена.
Щоб існував допустимий розріз, загальна кількість простих чисел у масиві має ділитися на . Якщо ні, відповідь дорівнює . В іншому випадку розглядайте задачу як розміщення точок розрізу між групами рівно з простих чисел. Між послідовними групами з простих чисел можуть бути деякі непрості елементи. Кожен непростий елемент у такому проміжку може належати або лівому підмасиву, або правому, що дає вільний бінарний вибір для кожного елемента проміжку — тому проміжок розміру вносить мультиплікативний множник g + 1 до відповіді.
Точніше, проходьте масив зліва направо, підтримуючи лічильник простих чисел, побачених у поточній групі, та лічильник для кількості способів розмістити поточний розріз:
Коли зустрічається непросте число і \mathit{cnt} = k, збільшіть на (ще одна допустима позиція розрізу).
Коли зустрічається просте число і \mathit{cnt} = k, помножте на , скиньте \mathit{check} = 1 і \mathit{cnt} = 0, потім збільшіть на .
Наприкінці, якщо остання група не містить рівно простих чисел, виведіть . Інакше виведіть \mathit{ans} \bmod (10^9 + 7).
Розв'язок працює за час \mathcal{O}\!\left(A \log \log A + \sum n\right) на тестовий файл, де A = 10^7 — межа решета, а \sum n \le 2 \times 10^5 — загальний розмір вхідних даних по всіх тестових випадках.
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MAX = 1e7 + 1, mod = 1e9 + 7;
vector<bool> is_prime(MAX, true);
void sieve() {
is_prime[0] = is_prime[1] = false;
for (int i = 2; i * i < MAX; i++)
if (is_prime[i])
for (int j = i * i; j < MAX; j += i)
is_prime[j] = false;
}
void solve() {
int n, k, cnt = 0, check = 1;
cin >> n >> k;
ll ans = 1;
for (int i = 0; i < n; i++) {
int x; cin >> x;
if (!is_prime[x]) {
if (cnt == k) check++;
} else {
if (cnt == k) {
ans = ans * check % mod;
check = 1; cnt = 0;
}
cnt++;
}
}
if (cnt != k) { cout << 0; return; }
cout << ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
sieve();
int t; cin >> t;
while (t--) { solve(); cout << '\n'; }
return 0;
}