数列互质
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int M = 5 * 1e4 + 10;
const int MOD = 109;
int n, m, unit, ans;
int a[M], Be[M], sum[M];
struct node {
int l, r, k, id, ans;
} e[M];
set<int> s;
bool cmp(node a, node b) {
return Be[a.l] == Be[b.l] ? a.r < b.r : a.l < b.l;
}
bool cmp2(node a, node b) {
return a.id < b.id;
}
ll GCD(ll a, ll b) {
while (b ^= a ^= b ^= a %= b)
;
return a;
}
void revise(int x, int add) {
sum[a[x]] += add;
}
int main() {
cin >> n >> m;
unit = sqrt(n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]), Be[i] = i / unit + 1;
s.insert(a[i]);
}
for (int i = 1; i <= m; ++i) {
scanf("%d%d%d", &e[i].l, &e[i].r, &e[i].k);
e[i].id = i;
}
sort(e + 1, e + m + 1, cmp);
int l = 1, r = 0;
for (int i = 1; i <= m; ++i) {
while (l < e[i].l)
revise(l, -1), l++;
while (l > e[i].l)
revise(l - 1, 1), l--;
while (r < e[i].r)
revise(r + 1, 1), r++;
while (r > e[i].r)
revise(r, -1), r--;
ans = 0;
set<int>::iterator it;
for (it = s.begin(); it != s.end(); it++) {
if (sum[*it] && GCD(sum[*it], e[i].k) == 1)
ans++;
}
e[i].ans = ans;
}
sort(e + 1, e + m + 1, cmp2);
for (int i = 1; i <= m; ++i) {
cout << e[i].ans << endl;
}
return 0;
}
题解:莫队的基础版本,每次都要对所有数字进行一次遍历,这里用set记录,避免重复,每次重新算最大公约数依次累加就行