BZOJ-4542: [Hnoi2016]大数 (莫队算法)

4542: [Hnoi2016]大数

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 1637  Solved: 568
[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

Sample Output

5
3
2
//第一个询问问的是整个串,满足条件的子串分别有:121121,2112,11,121,121。

HINT

 2016.4.19新加数据一组

Source

T了两个点什么鬼qwq

 1 #include "bits/stdc++.h"
 2 using namespace std;
 3 typedef long long LL;
 4 const int MAX=1e6+5;
 5 LL n,m,p,bas,pos[MAX];
 6 LL a[MAX],b[MAX],d[MAX],an[MAX],ans;
 7 LL ab[MAX],cd[MAX];
 8 char s[MAX];
 9 struct Node{
10     int id;
11     int l,r;
12     bool operator < (const Node &tt) const {
13         if (pos[l]!=pos[tt.l])
14             return pos[l]<pos[tt.l];
15         return r<tt.r;
16     }
17 }que[MAX];
18 inline LL read(){
19     LL an=0,x=1;char c=getchar();
20     while (c<'0' || c>'9') {if (c=='-') x=-1;c=getchar();}
21     while (c>='0' && c<='9') {an=an*10+c-'0';c=getchar();}
22     return an*x;
23 }
24 int main(){
25     freopen ("huge.in","r",stdin);freopen ("huge.out","w",stdout);
26     LL i,j,cnt=1,x,y;
27     scanf("%lld
",&p);scanf("%s",s+1); n=strlen(s+1);bas=(LL)sqrt(n*1.0);
28     if (p==2 || p==5){
29         for (i=1;i<=n;i++){
30             if ((s[i]-'0')%p==0)
31                 ab[i]=ab[i-1]+1,cd[i]=cd[i-1]+i;
32             else ab[i]=ab[i-1],cd[i]=cd[i-1];
33         }
34         m=read();
35         for (i=1;i<=m;i++){
36             x=read(),y=read();
37             printf("%lld
",cd[y]-cd[x-1]-(ab[y]-ab[x-1])*(x-1));
38         }
39         return 0;
40     }
41     for (i=n;i>=1;i--){
42         cnt=(cnt*10)%p;
43         b[i]=a[i]=((s[i]-'0')*cnt+a[i+1])%p;
44     }
45     sort(b+1,b+n+1);
46     for (i=1;i<=n+1;i++) a[i]=lower_bound(b+1,b+n+1,a[i])-b;
47     m=read();
48     for (i=1;i<=m;i++){
49         que[i].id=i;
50         que[i].l=read(),que[i].r=read();que[i].r++;
51     }
52     sort(que+1,que+m+1);
53     int L=1,R=0;
54     for (i=1;i<=m;i++){
55         while(R<que[i].r) ans+=ab[a[++R]]++;
56         while(L>que[i].l) ans+=ab[a[--L]]++;
57         while(L<que[i].l) ans-=--ab[a[L++]];
58         while(R>que[i].r) ans-=--ab[a[R--]];
59         an[que[i].id]=ans;
60     }
61     for (i=1;i<=m;i++)
62         printf("%lld
",an[i]);
63     return 0;
64 }
未来是什么样,未来会发生什么,谁也不知道。 但是我知道, 起码从今天开始努力, 肯定比从明天开始努力, 要快一天实现梦想。 千里之行,始于足下! ——《那年那兔那些事儿》
原文地址:https://www.cnblogs.com/keximeiruguo/p/7719802.html