Solution
General Idea: We need to count, for each query, the triples (i, j, k) whose gcd lies in [l, r]. The key is to compute, for every value , the number of triples whose gcd is exactly , and then answer queries with prefix sums.
Let be the number of elements equal to . Since a_i \le n, every gcd is also at most .
For each , let sum_g be the number of elements divisible by :
Every triple chosen from these elements has a gcd that is a multiple of . So the number of triples whose gcd is a multiple of is:
Let exact(g) be the number of triples whose gcd is exactly . Then counts exact(g) plus the triples whose gcd is a larger multiple of :
We compute this for from down to , so all larger multiples are already known when we reach .
After that, we build prefix sums over , so a query (l, r) is answered in by:
The binomial coefficients are computed with precomputed factorials and inverse factorials modulo 10^9 + 7.
Computing sum_g and the inclusion-exclusion step both iterate over the multiples of each , which is a harmonic sum. So the solution runs in \mathcal{O}(n \log n + q) per test case, after the one-time factorial precomputation.
#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e9 + 7, N = 1e6 + 5;
long long fact[N], invFact[N];
long long power(long long x, long long y, long long p) {
long long res = 1;
x = x % p;
while (y > 0) {
if (y & 1) res = (res * x) % p;
y = y >> 1;
x = (x * x) % p;
}
return res;
}
void precompute() {
fact[0] = 1;
for (long long i = 1; i < N; i++) fact[i] = (fact[i - 1] * i) % mod;
invFact[N - 1] = power(fact[N - 1], mod - 2, mod);
for (long long i = N - 2; i >= 0; i--)
invFact[i] = (invFact[i + 1] * (i + 1)) % mod;
}
long long nCr(long long n, long long r) {
if (r > n || n < 0 || r < 0) return 0;
return ((fact[n] * invFact[r]) % mod * invFact[n - r]) % mod;
}
void solve() {
int n, q;
cin >> n >> q;
vector<long long> gd(n + 1, 0), cnt(n + 1, 0);
for (int i = 0; i < n; i++) {
int x;
cin >> x;
cnt[x]++;
}
for (int i = 1; i <= n; i++) {
int sum = 0;
for (int j = i; j <= n; j += i) {
sum += cnt[j];
}
gd[i] = nCr(sum, 3);
}
for (int i = n; i >= 1; i--) {
for (int j = 2 * i; j <= n; j += i) {
gd[i] -= gd[j];
if (gd[i] < 0) gd[i] += mod;
}
}
for (int i = 1; i <= n; i++) {
gd[i] = (gd[i] + gd[i - 1]) % mod;
}
while (q--) {
int l, r;
cin >> l >> r;
long long ans = gd[r] - gd[l - 1];
if (ans < 0) ans += mod;
cout << ans % mod << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(NULL);
precompute();
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}