結果
問題 |
No.3026 Range LCM (Online Version)
|
ユーザー |
|
提出日時 | 2025-09-06 08:27:29 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 2,072 ms / 3,000 ms |
コード長 | 3,227 bytes |
コンパイル時間 | 4,916 ms |
コンパイル使用メモリ | 261,404 KB |
実行使用メモリ | 482,864 KB |
最終ジャッジ日時 | 2025-09-06 08:28:24 |
合計ジャッジ時間 | 50,416 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 1 |
other | AC * 37 |
ソースコード
#include <bits/stdc++.h> #include <atcoder/all> using namespace std; using ll = long long; using mint = atcoder::modint998244353; template <class mint> struct StaticRangeLCM { int N, logN, mx; std::vector<int> mn_pr; std::vector<std::vector<pair<int, mint>>> dat; StaticRangeLCM(std::vector<int> &a) : N(a.size()), mx(*std::max_element(a.begin(), a.end())), mn_pr(mx + 1) { logN = ceil_pow2(a.size()); N = 1 << logN; dat.resize(2 * N); std::vector<mint> inv(mx + 1); // 各数を割り切る最小の素数を代入 // 逆数を代入 mn_pr[0] = mn_pr[1] = -1; for(int i = 2; i <= mx; i++){ inv[i] = mint(i).inv(); if(mn_pr[i] != 0) continue; for(int j = i; j <= mx; j += i){ if(mn_pr[j] == 0) mn_pr[j] = i; } } vector<int> pos(mx + 1, -1); for(int i = 0; i < (int)(a.size()); i++){ if(a[i] == 1) continue; int v = a[i], prv = -1, tmp = 0; dat[i + N].emplace_back(i, v); while(v != 1){ if(mn_pr[v] == prv) tmp *= mn_pr[v]; else tmp = mn_pr[v]; if(pos[tmp] != -1) dat[pos[tmp] + N].emplace_back(i, inv[mn_pr[tmp]]); pos[tmp] = i; prv = mn_pr[v]; v /= mn_pr[v]; } } auto comp = [](pair<int, mint> lhs, pair<int, mint> rhs){ return lhs.first < rhs.first; }; for(int y = N - 1; y >= 1; y--){ int Li = 2 * y, Ri = 2 * y + 1; std::merge(dat[Li].begin(), dat[Li].end(), dat[Ri].begin(), dat[Ri].end(), std::back_inserter(dat[y]), comp); } for(int i = 2 * N - 1; i >= 1; i--){ int cn = dat[i].size(); for(int j = 0; j + 1 < cn; j++){ dat[i][j + 1].second *= dat[i][j].second; } } } mint prod(int l, int r){ mint mul = 1, div = 1; int L = l + N, R = r + N; while(L < R){ if(L & 1){ mul *= get(L, r); div *= get(L++, l); } if(R & 1){ mul *= get(--R, r); div *= get(R, l); } L >>= 1, R >>= 1; } return mul / div; } private: mint get(int p, int r){ int ng = -1, ok = dat[p].size(); while(ng + 1 < ok){ int mid = (ok + ng) / 2; (dat[p][mid].first >= r ? ok : ng) = mid; } return ok >= 1 ? dat[p][ok - 1].second : 1; } int ceil_pow2(int n) { int x = 0; while ((1U << x) < (unsigned int)(n)) x++; return x; } }; int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin >> n; vector<int> a(n); for(auto &&v : a) cin >> v; StaticRangeLCM<mint> RLCM(a); int Q; cin >> Q; mint ans = 1; while(Q--){ int a, b; cin >> a >> b; int l = (a * ans).val() % n, r = (b * ans).val() % n; if(l > r) swap(l, r); r++; ans = RLCM.prod(l, r); cout << ans.val() << '\n'; } }