Title Description
Give a number string and ask multiple times how many sub-intervals correspond to multiples of p. where P is prime.
Input
The first line is an integer: P. The second line is a string: S. The third line is an integer: M. Next m line, two integers per line fr,to, represents a query to the substring of S s[fr...to]. Note: The leftmost number of S has a position ordinal of 1; For example, S is 213567, then s[1] is 2,s[1 ... 3] is 213.
N,m<=100000,p as prime number
Output
Output m lines, one integer per line, and line I is the answer to the I query.
Sample input
11
121121
3
1 6
1 5
1 4
Sample output
5
3
2
Exercises
MO Team Algorithm
Set $b [i]=s[i...n]\ \text{mod}\ p$, then $S [l,r]$ is a multiple of $p $ when and only if: $\frac{b[l]-b[r+1]}{10^{r-l}}\ \text{mod}\ p=0$.
When $p =2$ or $p =5$, it is not a multiple of $p $ to be judged directly by the number string. Set $v [i]=[i\ \text{mod}\ p=0]$, maintain $v [i]$ and $v [i] i$ prefixes and quickly get answers.
When $p \neq 2$ and $p \neq 5$, $p $ with $10$ coprime. At this point the condition is simplified to: $b [l]\equiv b[r+1]\ (\text{mod}\ p) $.
So the original problem translates to the number of pairs that $b $ value equal within the $[l,r+1]$.
The $b $ discretization, using the MO team algorithm, the use of buckets to maintain a discrete $b $ number of occurrences, the pointer moves when the statistical answer can be.
Time Complexity $O (n\log N) $
#include <cmath> #include <cstdio> #include <cstring> #include <algorithm> #define N 100010using Namespace Std;typedef Long Long ll;ll P;char str[n];namespace task1{ll S1[n], s2[n]; void Solve () {int n, m, I, L, R; scanf ("%s%d", str + 1, &m), n = strlen (str + 1); for (i = 1; I <= n; i + +) {S1[i] = S1[i-1], s2[i] = s2[i-1]; if ((Str[i]-' 0 ')% p = = 0) s1[i] + +, s2[i] + = i; } while (M--) {scanf ("%d%d", &l, &r); printf ("%lld\n", S2[r]-s2[l-1]-(L-1) * (S1[r]-s1[l-1])); }}}namespace task2{struct data {int L, R, BL, ID; BOOL operator< (const data &a) Const {return BL = = A.BL R < A.r:bl < A.BL;} }q[n]; int a[n], mp[n]; ll B[n], V[n], ans[n]; void Solve () {int n, m, I, SI, LP = 1, RP = 0; ll t = 1, now = 0; scanf ("%s%d", str +1, &m), n = strlen (str + 1), si = (int) sqrt (n); for (i = n; i; I--, t = t * ten p) v[i] = b[i] = (b[i + 1] + (Str[i]-' 0 ') * t)% P; V[n + 1] = 0, sort (v + 1, v + n + 2); for (i = 1; I <= n + 1; i + +) a[i] = Lower_bound (v + 1, v + n + 2, b[i])-V; for (i = 1; I <= m; i + +) scanf ("%d%d", &Q[I].L, &Q[I].R), Q[I].R + +, Q[I].BL = (q[i].l-1)/SI, q[i]. id = i; Sort (q + 1, q + M + 1); for (i = 1; I <= m; i + +) {while (LP > Q[I].L) Now + = Mp[a[--lp]], MP[A[LP]] + +; while (RP < Q[I].R) Now + = Mp[a[++rp]], MP[A[RP]] + +; while (LP < Q[I].L) MP[A[LP] [--, now-= mp[a[lp++]]; while (Rp > Q[I].R) MP[A[RP] [--, now-= mp[a[rp--]]; Ans[q[i].id] = now; } for (i = 1; I <= m; i + +) printf ("%lld\n", Ans[i]); }}int Main () {scanf ("%lld", &p); if (p = = 2 | | p = = 5) task1::solve (); else Task2::solve (); RetUrn 0;}
"bzoj4542" [Hnoi2016] large number MO team algorithm