洛谷P3245 [HNOI2016]大数(莫队)
程序员文章站
2022-12-15 18:16:19
题意 "题目链接" Sol 莫队板子题。。 维护出每个位置开始的字符串$mod P$的结果,记为$S_i$ 两个位置$l, r$满足条件当且仅当$S_l S_r = 0$,也就是$S_l = S_r$ 离散化之后直接上莫队就行了 对$2, 5$特判一下,因为2/5是10的因子,可能导致答案变大。直接 ......
题意
sol
莫队板子题。。
维护出每个位置开始的字符串\(mod p\)的结果,记为\(s_i\)
两个位置\(l, r\)满足条件当且仅当\(s_l - s_r = 0\),也就是\(s_l = s_r\)
离散化之后直接上莫队就行了
对\(2, 5\)特判一下,因为2/5是10的因子,可能导致答案变大。直接维护\(0/5\)的出现次数就可以了
考场上一高兴写了三个subtask。。
#include <bits/stdc++.h> #define ll long long using namespace std; const int maxn = 1e6 + 10; int mod; template <typename a, typename b> inline void mul2(a &x, b y) { x = 1ll * x * y % mod; } template <typename a, typename b> inline int mul(a x, b y) { return 1ll * x * y % mod; } template <typename a, typename b> inline int add(a x, b y) { return x + y >= mod ? x + y - mod : x + y; } inline int read() { char c = getchar(); int x = 0, f = 1; while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int n, q, belong[maxn], block, l, r; ll now, ans[maxn]; char s[maxn]; namespace sub3 { int pro[maxn], num, date[maxn], cnt[maxn]; void des() { for (int i = 1; i <= n + 1; i++) date[++num] = pro[i]; sort(date + 1, date + num + 1); num = unique(date + 1, date + num + 1) - date - 1; for (int i = 1; i <= n + 1; i++) pro[i] = lower_bound(date + 1, date + num + 1, pro[i]) - date; } struct query { int l, r, id; bool operator<(const query &rhs) const { return belong[l] == belong[rhs.l] ? r < rhs.r : belong[l] < belong[rhs.l]; } } q[maxn]; void add(int x) { now += cnt[x]; cnt[x]++; } void delet(int x) { cnt[x]--; now -= cnt[x]; } void solve() { block = sqrt(n); for (int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1; for (int i = n, base = 1; i >= 1; i--, mul2(base, 10)) pro[i] = add(pro[i + 1], mul((s[i] - '0'), base)); des(); q = read(); for (int i = 1; i <= q; i++) q[i].l = read(), q[i].r = read() + 1, q[i].id = i; sort(q + 1, q + q + 1); l = 1, r = 0; for (int i = 1; i <= q; i++) { while (r < q[i].r) add(pro[++r]); while (r > q[i].r) delet(pro[r--]); while (l < q[i].l) delet(pro[l++]); while (l > q[i].l) add(pro[--l]); ans[q[i].id] = now; } for (int i = 1; i <= q; i++) cout << ans[i] << '\n'; } } // namespace sub3 namespace sub1 { int cnt[maxn], a[maxn]; struct query { int l, r, id; bool operator<(const query &rhs) const { return belong[l] == belong[rhs.l] ? r < rhs.r : belong[l] < belong[rhs.l]; } } q[maxn]; void add(int x, int opt) { if (opt) { if (x == 0) now += r - l + 1; } else { now += cnt[0]; } cnt[x]++; } void delet(int x, int opt) { cnt[x]--; if (opt) { if (x == 0) now -= r - l + 1; } else { now -= cnt[0]; } } void solve() { block = sqrt(n); for (int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1, a[i] = (s[i] - '0') % 2; q = read(); for (int i = 1; i <= q; i++) q[i].l = read(), q[i].r = read(), q[i].id = i; sort(q + 1, q + q + 1); l = 1, r = 0; for (int i = 1; i <= q; i++) { while (r < q[i].r) add(a[++r], 1); while (r > q[i].r) delet(a[r--], 1); while (l < q[i].l) delet(a[l++], 0); while (l > q[i].l) add(a[--l], 0); ans[q[i].id] = now; } for (int i = 1; i <= q; i++) cout << ans[i] << '\n'; } } namespace sub2 { int cnt[maxn], a[maxn], len[maxn]; struct query { int l, r, id; bool operator < (const query &rhs) const { return belong[l] == belong[rhs.l] ? r < rhs.r : belong[l] < belong[rhs.l]; } }q[maxn]; void add(int x, int opt, int pos) { cnt[x]++; if(opt) { if(x == 0 || x == 5) now += r - l + 1; } else { now += cnt[0] + cnt[5]; } } void delet(int x, int opt, int pos) { if(opt) { if(x == 0 || x == 5) now -= r - l + 1; } else { now -= cnt[0] + cnt[5]; } cnt[x]--; } void solve() { block = sqrt(n); for(int i = 1; i <= n; i++) belong[i] = (i - 1) / block + 1, a[i] = s[i] - '0'; q = read(); for(int i = 1; i <= q; i++) q[i].l = read(), q[i].r = read(), q[i].id = i; sort(q + 1, q + q + 1); l = 1, r = 0; for(int i = 1; i <= q; i++) { while(l > q[i].l) --l, add(a[l], 0, l); while(r > q[i].r) delet(a[r], 1, r), r--; while(l < q[i].l) delet(a[l], 0, l), l++; while(r < q[i].r) ++r, add(a[r], 1, r); ans[q[i].id] = now; } for(int i = 1; i <= q; i++) cout << ans[i] << '\n'; } } int main() { mod = read(); scanf("%s", s + 1); n = strlen(s + 1); if (mod == 2) sub1::solve(); else if (mod == 5) sub2::solve(); else sub3::solve(); return 0; } /* 11 1211 1 1 4 */