看到取模瞬间想到了昨天的bc。
应该这是取模然后求啥玩意的时候的比较通用的解法吧。p<=sqrt(maxv)的预处理,剩下的直接暴力。结果预处理又写丑了一回。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 100009;
const int maxv = 10000;
const int bsz = 100;
const int maxb = 103;
int n, m;
int a[maxn], vb[maxb][maxb], ve[maxb][maxb];
int xb[maxn], xe[maxn];
int i_buf[maxn * maxb * 2], tib;
void pre() {
memset(ve, 0, sizeof(ve));
memset(xe, 0, sizeof(xe));
for (int i = 1; i <= n; ++ i)
++ xe[a[i]];
for (int i = 0; i <= maxv; ++ i) {
xb[i] = tib;
tib += xe[i];
xe[i] = xb[i];
}
for (int i = 1; i <= n; ++ i)
i_buf[xe[a[i]] ++] = i;
for (int m = 1; m <= bsz; ++ m) {
for (int i = 1; i <= n; ++ i)
++ ve[m][a[i] % m];
for (int i = 0; i < m; ++ i) {
vb[m][i] = tib;
tib += ve[m][i];
ve[m][i] = vb[m][i];
}
for (int i = 1; i <= n; ++ i)
i_buf[ve[m][a[i] % m] ++] = i;
}
}
int queryb(int l0, int r0, int p, int k) {
if (vb[p][k] == ve[p][k])
return 0;
int *x1 = lower_bound(i_buf + vb[p][k], i_buf + ve[p][k], l0);
int *x2 = upper_bound(i_buf + vb[p][k], i_buf + ve[p][k], r0);
return x2 - x1;
}
int querys(int v, int l0, int r0) {
if (xb[v] == xe[v])
return 0;
int *x1 = lower_bound(i_buf + xb[v], i_buf + xe[v], l0);
int *x2 = upper_bound(i_buf + xb[v], i_buf + xe[v], r0);
return x2 - x1;
}
int querya(int l0, int r0, int p, int k) {
int ans = 0;
for (int i = k; i <= maxv; i += p)
ans += querys(i, l0, r0);
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
scanf("%d%d", &n, &m);
tib = 0;
for (int i = 1; i <= n; ++ i)
scanf("%d", a + i);
pre();
while (m --) {
int l, r, p, k;
scanf("%d%d%d%d", &l, &r, &p, &k);
if (p <= bsz)
printf("%d\n", queryb(l, r, p, k));
else
printf("%d\n", querya(l, r, p, k));
}
}