理论上的复杂度是比莫队算法好的。。。。只是理论上的复杂度。。。
#include <bits/stdc++.h> using namespace std; typedef long long LL; #define ls o << 1 #define rs o << 1 | 1 #define lson o << 1, L, mid #define rson o << 1 | 1, mid + 1, R const int maxn = 10005; struct node { int l, r, id; node(int l = 0, int r = 0, int id = 0) : l(l), r(r), id(id) {} }q[maxn]; int st[maxn][15]; LL ans[maxn]; int p[maxn]; int a[maxn]; LL add[maxn << 2]; LL sum[maxn << 2]; int n, m; void st_init() { p[0] = -1; for(int i = 1; i<= n; i++) p[i] = i & (i-1) ? p[i-1] : p[i-1]+1; for(int i = 1; i <= n; i++) st[i][0] = a[i]; for(int j = 1; j <= p[n]; j++) for(int i = 1; i + (1 << j) - 1 <= n; i++) st[i][j] = __gcd(st[i][j-1], st[i+(1<<j-1)][j-1]); } int gcd(int l, int r) { int k = p[r - l + 1]; return __gcd(st[l][k], st[r-(1<<k)+1][k]); } int find(int s, int t) { int top = n, bot = t, res = n, mid; while(top >= bot) { mid = (top + bot) >> 1; if(gcd(s, t) == gcd(s, mid)) res = mid, bot = mid+1; else top = mid-1; } return res; } int cmp(node a, node b) { return a.l > b.l; } void pushup(int o) { sum[o] = sum[ls] + sum[rs]; } void pushdown(int o, int L, int R) { if(add[o]) { int mid = (L + R) >> 1; sum[ls] += (mid - L + 1) * add[o]; sum[rs] += (R - mid) * add[o]; add[ls] += add[o]; add[rs] += add[o]; add[o] = 0; } } void update(int o, int L, int R, int ql, int qr, LL v) { if(ql <= L && qr >= R) { sum[o] += (R - L + 1) * v; add[o] += v; return; } pushdown(o, L, R); int mid = (L + R) >> 1; if(ql <= mid) update(lson, ql, qr, v); if(qr > mid) update(rson, ql, qr, v); pushup(o); } LL query(int o, int L, int R, int ql, int qr) { if(ql <= L && qr >= R) return sum[o]; pushdown(o, L, R); int mid = (L + R) >> 1; LL res = 0; if(ql <= mid) res += query(lson, ql, qr); if(qr > mid) res += query(rson, ql, qr); pushup(o); return res; } void build(int o, int L, int R) { sum[o] = add[o] = 0; if(L == R) return; int mid = (L + R) >> 1; build(lson); build(rson); } void work() { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d", &a[i]); st_init(); scanf("%d", &m); for(int i = 1; i <= m; i++) { int l, r; scanf("%d%d", &l, &r); q[i] = node(l, r, i); } sort(q+1, q+m+1, cmp); build(1, 1, n); for(int i = n, j = 1; j <= m; i--) { int t = i; while(t <= n) { int nt = find(i, t); update(1, 1, n, t, nt, gcd(i, t)); t = nt + 1; } while(j <= m && q[j].l >= i) { ans[q[j].id] = query(1, 1, n, q[j].l, q[j].r); j++; } } for(int i = 1; i <= m; i++) printf("%lld\n", ans[i]); } int main() { int _; scanf("%d", &_); while(_--) work(); return 0; }