4542: [Hnoi2016]大数
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 993 Solved: 360
[ Submit][ Status][ Discuss]
Description
小 B 有一个很大的数 S,长度达到了 N 位;这个数可以看成是一个串,它可能有前导 0,例如00009312345
。小B还有一个素数P。现在,小 B 提出了 M 个询问,每个询问求 S 的一个子串中有多少子串是 P 的倍数(0 也
是P 的倍数)。例如 S为0077时,其子串 007有6个子串:0,0,7,00,07,007;显然0077的子串007有6个子串都是素
数7的倍数。
Input
第一行一个整数:P。第二行一个串:S。第三行一个整数:M。接下来M行,每行两个整数 fr,to,表示对S 的
子串S[fr…to]的一次询问。注意:S的最左端的数字的位置序号为 1;例如S为213567,则S[1]为 2,S[1…3]为 2
13。N,M<=100000,P为素数
Output
输出M行,每行一个整数,第 i行是第 i个询问的答案。
Sample Input
11
121121
3
1 6
1 5
1 4
121121
3
1 6
1 5
1 4
Sample Output
5
3
2
//第一个询问问的是整个串,满足条件的子串分别有:121121,2112,11,121,121。
3
2
//第一个询问问的是整个串,满足条件的子串分别有:121121,2112,11,121,121。
HINT
2016.4.19新加数据一组
Source
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1E6 + 10;
typedef long long LL;
const int A[5] = {0,2,4,6,8};
const int B[2] = {0,5};
struct Query{
int l,r,flag,num; Query(){}
Query(int l,int r,int flag,int num): l(l),r(r),flag(flag),num(num){}
bool operator < (const Query &b) const
{
if (flag < b.flag) return 1;
if (flag > b.flag) return 0;
return r < b.r;
}
}Q[maxn];
LL p,tot,suf[maxn],ans[maxn],a[maxn],sum[maxn],g[maxn];
int n,m,L = 1,R,Sqrt,cur = 1,cnt[maxn];
char s[maxn];
bool f1,f2;
void Inc(int k)
{
++cnt[suf[k]];
tot += 1LL*(cnt[suf[k]] - 1);
}
void Dec(int k)
{
tot -= 1LL*(cnt[suf[k]] - 1);
--cnt[suf[k]];
}
void Solve()
{
for (int i = 1; i <= n; i++,sum[i] = sum[i-1],g[i] = g[i-1])
if (f1)
{
for (int j = 0; j < 5; j++)
if (A[j] == s[i] - '0')
sum[i] += 1LL*i,g[i] += 1LL;
}
else
{
for (int j = 0; j < 2; j++)
if (B[j] == s[i] - '0')
sum[i] += 1LL*i,g[i] += 1LL;
}
cin >> m;
for (int i = 1; i <= m; i++)
{
int l,r; scanf("%d%d",&l,&r);
printf("%lld\n",sum[r] - sum[l-1] - 1LL*(l-1)*(g[r] - g[l-1]));
}
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> p; LL t = 1;
if (p == 2) f1 = 1;
if (p == 5) f2 = 1;
scanf("%s",s + 1);
n = strlen(s + 1);
if (f1 || f2) {Solve(); return 0;} ++n;
s[n] = '0'; Sqrt = sqrt(n);
for (int i = n; i; i--)
{
LL x = s[i] - '0';
suf[i] = suf[i+1] + x*t;
suf[i] %= p;
t *= 10LL; t %= p;
a[++tot] = suf[i];
}
sort(a + 1,a + tot + 1);
for (int i = 2; i <= tot; i++)
if (a[i] != a[i-1])
a[++cur] = a[i];
tot = 0;
for (int i = 1; i <= n; i++)
suf[i] = lower_bound(a + 1,a + cur + 1,suf[i]) - a;
cin >> m;
for (int i = 1; i <= m; i++)
{
int l,r; scanf("%d%d",&l,&r);
if (!f1 && !f2)
Q[i] = Query(l,r+1,l % Sqrt == 0?l / Sqrt:l / Sqrt + 1,i);
else Q[i] = Query(l,r,l % Sqrt == 0?l / Sqrt:l / Sqrt + 1,i);
}
sort(Q + 1,Q + m + 1);
for (int i = 1; i <= m; i++)
{
while (R < Q[i].r) Inc(++R);
while (Q[i].l < L) Inc(--L);
while (L < Q[i].l) Dec(L),++L;
while (Q[i].r < R) Dec(R),--R;
ans[Q[i].num] = tot;
}
for (int i = 1; i <= m; i++) printf("%lld\n",ans[i]);
return 0;
}