把询问离线, 我们从n 到 1遍历过去的时候, 把(1 - 1 / p)乘在最靠近当前位置的地方, 然后区间求乘积就好啦。
#include<bits/stdc++.h> #define LL long long #define fi first #define se second #define mk make_pair #define PLL pair<LL, LL> #define PLI pair<LL, int> #define PII pair<int, int> #define SZ(x) ((int)x.size()) #define ull unsigned long long using namespace std; const int N = 1e6 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; struct SegmentTree { #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 int a[N << 2]; void build(int *b, int l, int r, int rt) { if(l == r) { a[rt] = b[l]; return; } int mid = l + r >> 1; build(b, lson); build(b, rson); a[rt] = 1ll * a[rt << 1] * a[rt << 1 | 1] % mod; } void update(int p, int val, int l, int r, int rt) { if(l == r) { a[rt] = 1ll * a[rt] * val % mod; return; } int mid = l + r >> 1; if(p <= mid) update(p, val, lson); else update(p, val, rson); a[rt] = 1ll * a[rt << 1] * a[rt << 1 | 1] % mod; } int query(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) return a[rt]; int mid = l + r >> 1; if(R <= mid) return query(L, R, lson); else if(L > mid) return query(L, R, rson); else return (1ll * query(L, R, lson) * query(L, R, rson)) % mod; } }; int n, q, a[N], mul[N], del[N], ans[N], Map[N]; vector<int> prime; vector<int> fac[N]; vector<PII> qus[N]; SegmentTree seg; int Power(int a, int b) { int ans = 1; while(b) { if(b & 1) ans = 1ll * ans * a % mod; a = 1ll * a * a % mod; b >>= 1; } return ans; } int main() { for(int i = 2; i < N; i++) { if(SZ(fac[i])) continue; prime.push_back(i); for(int j = i; j < N; j += i) fac[j].push_back(i); } for(auto& x : prime) { mul[x] = (1 - Power(x, mod - 2) + mod) % mod; del[x] = Power(mul[x], mod - 2); } scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); seg.build(a, 1, n, 1); scanf("%d", &q); for(int i = 1; i <= q; i++) { int L, R; scanf("%d%d", &L, &R); qus[L].push_back(mk(R, i)); } for(int i = n; i >= 1; i--) { for(auto& t : fac[a[i]]) { if(Map[t]) seg.update(Map[t], del[t], 1, n, 1); seg.update(i, mul[t], 1, n, 1); Map[t] = i; } for(auto& t : qus[i]) { ans[t.se] = seg.query(i, t.fi, 1, n, 1); } } for(int i = 1; i <= q; i++) printf("%d\n", ans[i]); return 0; } /* */