zoukankan      html  css  js  c++  java
  • bzoj4542 [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]为 213。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新加数据一组

    正解:莫队算法。

    考虑每次端点移动以后能产生的新贡献。用一个数组val[i]表示这个数只保留前i位上的数,其他位都是0的数模p的余数。那么如果val[l-1]=val[r],那么[l,r]区间上这个数模p=0。所以只要求出这个数组,并把n+1,同时n+1位为0,所有询问的右端点+1,这样,就能很好处理了。当指针移动时,只要查询与当前val相等的个数即可。因为val很大,所以要离散化。注意p=2或5时要加特判,因为只要最后一位模2或5为0,那么这个数就是2或5的倍数。所以就很容易了。

     1 //It is made by wfj_2048~
     2 #include <algorithm>
     3 #include <iostream>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cstdio>
     7 #include <vector>
     8 #include <cmath>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 #define inf (1<<30)
    14 #define il inline
    15 #define RG register
    16 #define ull unsigned long long
    17 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
    18 
    19 using namespace std;
    20 
    21 struct node{ ull l,r,i; }q[100010];
    22 
    23 ull c[100010],bl[100010],po[100010],val[100010],num[100010],hsh[100010],ans[100010],pp[100010],pre[100010],n,m,p,tot,block;
    24 char s[100010];
    25 
    26 il ull gll(){
    27     RG ull x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    28     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
    29 }
    30 
    31 il int cmp(const node &a,const node &b){ return bl[a.l]<bl[b.l] || (bl[a.l]==bl[b.l] && a.r<b.r); }
    32 
    33 il void solve(){
    34     for (RG ull i=1;i<=n;++i) pre[i]=pre[i-1]+((s[i]-48)%p==0),pp[i]=pp[i-1]+i*((s[i]-48)%p==0);
    35     for (RG ull i=1;i<=m;++i){
    36     RG ull l=gll(),r=gll();
    37     printf("%llu
    ",pp[r]-pp[l-1]-(pre[r]-pre[l-1])*(l-1));
    38     }
    39     return;
    40 }
    41 
    42 il void work(){
    43     scanf("%llu%s%llu",&p,s+1,&m); n=strlen(s+1);
    44     if (p==2 || p==5){ solve(); return; } block=sqrt(n);
    45     for (RG ull i=1;i<=m;++i) q[i].l=gll(),q[i].r=gll()+1,q[i].i=i;
    46     for (RG ull i=1;i<=n;++i) bl[i]=(i-1)/block+1; sort(q+1,q+m+1,cmp);
    47     po[n]=1; for (RG ull i=n-1;i;--i) po[i]=po[i+1]*10%p;
    48     for (RG ull i=n;i;--i) num[i]=val[i]=(val[i+1]+(s[i]-48)*po[i])%p; sort(num+1,num+n+2);
    49     hsh[tot=1]=num[1]; for (RG ull i=2;i<=n+1;++i) if (num[i]>num[i-1]) hsh[++tot]=num[i];
    50     for (RG ull i=1;i<=n+1;++i) val[i]=lower_bound(hsh+1,hsh+tot+1,val[i])-hsh; ull L=1,R=0,Ans=0;
    51     for (RG ull i=1;i<=m;++i){
    52     while (L>q[i].l) L--,Ans+=c[val[L]],c[val[L]]++;
    53     while (R<q[i].r) R++,Ans+=c[val[R]],c[val[R]]++;
    54     while (L<q[i].l) c[val[L]]--,Ans-=c[val[L]],L++;
    55     while (R>q[i].r) c[val[R]]--,Ans-=c[val[R]],R--;
    56     ans[q[i].i]=Ans;
    57     }
    58     for (RG ull i=1;i<=m;++i) printf("%llu
    ",ans[i]); return;
    59 }
    60 
    61 int main(){
    62     File("number");
    63     work();
    64     return 0;
    65 }
  • 相关阅读:
    我的那些年(11)~去一家创业公司做架构师
    springboot~hazelcast缓存中间件
    我的那些年(10)~来到更大的团队,做了架构师
    springboot~maven制作底层公用库
    Vesions ignore & ld: library not found for -l...
    iOS利用单例实现不同界面间的数据传输
    UVA 10006
    VS2010打开就自动关闭问题解决
    模板方法模式(Template Method)
    HDU 4279
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6416586.html
Copyright © 2011-2022 走看看