先套一下约数个数公式。
然后注意到可以把所有约数一起拿出来跑莫队,但是会被卡。
考虑类似于根号分治的东西,即出现次数较多的质数一般都比较小,所以把 ≤3√a 的质数都拿出来前缀和预处理,剩下至多只有 2 个质数,跑莫队。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5, M = 4e4 + 5, mod = 19260817;
int n, m, B, a[N];
unordered_map<int, int> st;
int pr[N + M], tot = 0;
int sum[N][205]; //小质数前缀和
int inv[N * 32];
vector<int> v[N]; //大质因数
struct node { int l, r, id; } p[N];
inline bool cmp(node a, node b) {
if ((a.l / B) ^ (b.l / B)) return a.l < b.l;
return ((a.l / B) & 1) ? (a.r < b.r) : (a.r > b.r);
}
int cnt[N + M];
long long res = 0;
inline void add(int x) { for (int i : v[x]) (res *= inv[cnt[i]]) %= mod, (res *= (++cnt[i])) %= mod; }
inline void del(int x) { for (int i : v[x]) (res *= inv[cnt[i]]) %= mod, (res *= (--cnt[i])) %= mod; }
void init() {
inv[1] = 1; for (int i = 2; i <= n * 32; i++) inv[i] = (mod - mod / i) * 1ll * inv[mod % i] % mod;
for (int i = 2; i <= 31630; i++) {
if (!st[i]) pr[++tot] = i, st[i] = tot;
for (int j = i + i; j <= 31630; j += i) st[j] = mod; //?
}
int qwq = tot;
for (int i = 1; i <= n; i++) {
int x = a[i];
for (int j = 1; j <= 200; j++) sum[i][j] = sum[i - 1][j];
for (int j = 1; j <= qwq && pr[j] <= x; j++) {
if (x % pr[j]) continue;
if (j <= 200) while (x % pr[j] == 0) x /= pr[j], sum[i][j]++; //小质数
else while (x % pr[j] == 0) x /= pr[j], v[i].push_back(j);
}
if (x > 1) {
if (!st[x]) pr[++tot] = x, st[x] = tot;
v[i].push_back(st[x]);
}
}
for (int i = 1; i <= tot; i++) cnt[i] = 1;
}
long long Ans[N];
int main() {
scanf("%d%d", &n, &m), B = sqrt(n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
init();
for (int i = 1; i <= m; i++) scanf("%d%d", &p[i].l, &p[i].r), p[i].id = i;
sort(p + 1, p + 1 + m, cmp);
int l = 1, r = 0; res = 1;
for (int i = 1; i <= m; i++) {
while (l > p[i].l) add(--l);
while (r > p[i].r) del(r--);
while (r < p[i].r) add(++r);
while (l < p[i].l) del(l++);
long long mul = 1;
for (int j = 1; j <= 200; j++) (mul *= (sum[p[i].r][j] - sum[p[i].l - 1][j] + 1) ) %= mod;
Ans[p[i].id] = (res * mul) % mod;
}
for (int i = 1; i <= m; i++) printf("%lld\n", Ans[i]);
return 0;
}