結果
問題 |
No.3026 Range LCM (Online Version)
|
ユーザー |
|
提出日時 | 2025-09-06 12:06:32 |
言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 1,049 ms / 3,000 ms |
コード長 | 4,053 bytes |
コンパイル時間 | 5,693 ms |
コンパイル使用メモリ | 260,484 KB |
実行使用メモリ | 160,692 KB |
最終ジャッジ日時 | 2025-09-06 12:07:18 |
合計ジャッジ時間 | 40,572 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> start; std::vector<std::pair<int, mint>> dat; StaticRangeLCM(std::vector<int> &a) : mx(*std::max_element(a.begin(), a.end())) { logN = ceil_pow2(a.size()); N = 1 << logN; start.resize(2 * N + 1); // 各数を割り切る最小の素数を代入 // 逆数を代入 std::vector<int> mn_pr(mx + 1); std::vector<mint> inv(mx + 1); for(int i = 2; i <= mx; i++){ if(mn_pr[i] != 0) continue; inv[i] = mint(i).inv(); for(int j = i; j <= mx; j += i){ if(mn_pr[j] == 0) mn_pr[j] = i; } } std::vector<std::pair<int, std::pair<int,mint>>> point; std::vector<int> pos(mx + 1, -1); std::vector<pair<int, mint>> lst(2 * N, make_pair(-1, 0)); for(int i = 0; i < (int)(a.size()); i++){ if(a[i] == 1) continue; int v = a[i], prv = -1, tmp = 0; for(int j = 0; j <= logN; j++){ int p = (i + N) >> j; if(lst[p].first != -1 && lst[p].first != i){ start[p + 1]++; point.emplace_back(p, lst[p]); } lst[p] = make_pair(i, a[i]); } while(v != 1){ if(mn_pr[v] == prv) tmp *= mn_pr[v]; else tmp = mn_pr[v]; if(pos[tmp] != -1){ int lv = pos[tmp] + N; for(int j = 0; j <= logN; j++){ int p = lv >> j; if(lst[p].first == i){ lst[p].second *= inv[mn_pr[tmp]]; }else{ start[p + 1]++; point.emplace_back(p, lst[p]); lst[p] = make_pair(i, inv[mn_pr[tmp]]); } } } pos[tmp] = i; prv = mn_pr[v]; v /= mn_pr[v]; } } for(int i = 1; i < 2 * N; i++){ if(lst[i].first == -1) continue; start[i + 1]++; point.emplace_back(i, lst[i]); } dat.resize(point.size()); for(int i = 0; i < 2 * N; i++) start[i + 1] += start[i]; auto cnt = start; for(auto &&[u, v] : point) dat[cnt[u]++] = v; for(int i = 1; i < 2 * N; i++){ int L = start[i], R = start[i + 1]; for(int j = L; j + 1 < R; j++){ dat[j + 1].second *= dat[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 = start[p] - 1, ok = start[p + 1]; while(ng + 1 < ok){ int mid = (ok + ng) / 2; (dat[mid].first >= r ? ok : ng) = mid; } return ok > start[p] ? dat[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'; } }