4542: [Hnoi2016]大数

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新加数据一组

 
题解:
把后缀模p的数搞出来离散化一下就可以上莫队了
注意p=2或p=5
code:
  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<algorithm>
  6 using namespace std;
  7 typedef long long int64;
  8 char ch;
  9 bool ok;
 10 void read(int &x){
 11     ok=0;
 12     for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
 13     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
 14     if (ok) x=-x;
 15 }
 16 void read(int64 &x){
 17     ok=0;
 18     for (ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
 19     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
 20     if (ok) x=-x;
 21 }
 22 const int maxn=100005;
 23 char s[maxn];
 24 int n,q,sn,x,y,bel[maxn],tot,cnt[maxn];
 25 int64 mod,a[maxn],ans[maxn],res,pw[maxn],list[maxn];
 26 struct Querys{
 27     int l,r,id;
 28     void init(int i){read(l),read(r),l=n-l+1,r=n-r+1,swap(l,r),l--,/*cout<<"FFFF "<<l<<' '<<r<<endl,*/id=i;}
 29 }querys[maxn];
 30 bool cmp(const Querys &a,const Querys &b){return bel[a.l]<bel[b.l]||(bel[a.l]==bel[b.l]&&bel[a.r]<bel[b.r]);}
 31 void modify(int col,int op){
 32     if (op==1) /*cout<<res<<' '<<col<<' '<<cnt[col]<<endl,*/res+=cnt[col],cnt[col]++;
 33     else cnt[col]--,res-=cnt[col];
 34 }
 35 void work(){
 36     int l=0,r=0; cnt[a[0]]=1,res=0;
 37     for (int i=1;i<=q;i++){
 38         for (;l<querys[i].l;l++) modify(a[l],-1);
 39         for (;l>querys[i].l;l--) modify(a[l-1],1);
 40         for (;r<querys[i].r;r++) modify(a[r+1],1);
 41 //      cout<<"res="<<res<<endl;
 42         for (;r>querys[i].r;r--) modify(a[r],-1);
 43         ans[querys[i].id]=res;
 44     }
 45 }
 46 int cnt2[maxn],cnt5[maxn];
 47 int64 ans2[maxn],ans5[maxn];
 48 int main(){
 49     read(mod);
 50     if (mod==2){
 51         scanf("%s",s+1),n=strlen(s+1);
 52         for (int i=1;i<=n;i++){
 53             cnt2[i]=cnt2[i-1],ans2[i]=ans2[i-1];
 54             if ((s[i]-'0')%2==0) cnt2[i]++,ans2[i]+=i;
 55         }
 56         for (read(q);q;q--){
 57             read(x),read(y);
 58             printf("%lld
",ans2[y]-1LL*(cnt2[y]-cnt2[x-1])*(x-1)-ans2[x-1]);
 59         }
 60     }
 61     else if (mod==5){
 62         scanf("%s",s+1),n=strlen(s+1);
 63         for (int i=1;i<=n;i++){
 64             cnt5[i]=cnt5[i-1],ans5[i]=ans5[i-1];
 65             if ((s[i]-'0')%5==0) cnt5[i]++,ans5[i]+=i;
 66         }
 67         for (read(q);q;q--){
 68             read(x),read(y);
 69             printf("%lld
",ans5[y]-1LL*(cnt5[y]-cnt5[x-1])*(x-1)-ans5[x-1]);
 70         }   
 71     }
 72     else{
 73         scanf("%s",s+1),n=strlen(s+1),sn=sqrt(n);
 74         for (int i=1,j=n;i<j;i++,j--) swap(s[i],s[j]);
 75         for (int i=0;i<=n;i++) bel[i]=i/sn;
 76     //  for (int i=0;i<=n;i++) cout<<i<<' ';cout<<endl;
 77     //  for (int i=0;i<=n;i++) cout<<bel[i]<<' ';cout<<endl;
 78         pw[0]=1;
 79         for (int i=1;i<=n;i++) pw[i]=1LL*pw[i-1]*10%mod;
 80         for (int i=1;i<=n;i++) a[i]=(a[i-1]+1LL*(s[i]-'0')*pw[i-1]%mod)%mod;
 81         for (int i=0;i<=n;i++) list[++tot]=a[i];
 82         sort(list+1,list+tot+1),tot=unique(list+1,list+tot+1)-list-1;
 83 //      for (int i=0;i<=n;i++) cout<<a[i]<<' ';cout<<endl;
 84         for (int i=0;i<=n;i++) a[i]=lower_bound(list+1,list+tot+1,a[i])-list;
 85 //      for (int i=0;i<=n;i++) cout<<a[i]<<' ';cout<<endl;
 86         read(q);
 87     //  cout<<q<<endl;
 88         for (int i=1;i<=q;i++) querys[i].init(i);
 89 //      for (int i=1;i<=q;i++) cout<<querys[i].l<<' '<<querys[i].r<<' '<<querys[i].id<<endl;
 90         sort(querys+1,querys+q+1,cmp);
 91         work();
 92         for (int i=1;i<=q;i++) printf("%lld
",ans[i]);
 93     }
 94     return 0;
 95 }
 96 /*
 97 11
 98 121121
 99 3
100 1 6
101 1 5
102 1 4
103 */
原文地址:https://www.cnblogs.com/chenyushuo/p/5416849.html