zoukankan      html  css  js  c++  java
  • [HNOI2016]大数

    题目描述

    小 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的倍数。

    输入输出格式

    输入格式:

    第一行一个整数: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为素数

    输出格式:

    输出M行,每行一个整数,第 i行是第 i个询问的答案。

    输入输出样例

    输入样例#1:
    11
    121121
    3
    1 6
    1 5
    1 4
    输出样例#1:
    5
    3
    2
    //第一个询问问的是整个串,满足条件的子串分别有:121121,2112,11,121,121。

    说明

    2016.4.19新加数据一组

    把每一个后缀i~n的值%p算出来lst[i]

    一个子串整除p满足:lst[i]=lst[j+1] (j>=i)

    所以用莫队处理询问,每一次移动都是很好计算的

    r向右走一步,相当于加上当前与lst[++r]相同的值ss[lst[++r]],在ss[lst[++r]]++

    r向左走一步,相当于减去当前与lst[r]相同的值ss[lst[r]]--,再把r--

    l相似

    注意上面的条件和下面的莫队处理的都是lst[i]=lst[j+1],所以要把询问的右端点+1

    还有要注意的,当p=2或p=5时要特判(不这样对不了)

    这两个素数比较特殊

    只要i能整除p,那么所有j~i都能整除p

    用ss[]表示 前缀有多少个可以被p整除的子串 ls[]表示有多少个可以被P整除的数 求区间多少个子串的时候用ss[r]-ss[l-1]-(l-1中整除p对区间l~r的贡献)

    =ss[r]-ss[l-1]-(l-1)*(ls[r]-ls[l-1])

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<map>
     7 using namespace std;
     8 typedef long long ll;
     9 struct Ask
    10 {
    11     ll id,l,r;
    12 }q[100005];
    13 ll sqn,m,n,lst[100005],ls[100005],ans[100005];
    14 ll ss[100005];
    15 map<ll,ll>Map;
    16 char s[100005];
    17 bool cmp(Ask a,Ask b)
    18 {
    19     if (a.l/sqn==b.l/sqn)
    20     return a.r<b.r;
    21     return a.l/sqn<b.l/sqn;
    22 }
    23 ll p;
    24 int main()
    25 {ll bt,i,l,r;
    26     cin>>p;
    27     cin>>s+1;
    28     cin>>m;
    29     n=strlen(s+1);
    30     sqn=sqrt(n);
    31     bt=1;
    32     if (p!=2&&p!=5)
    33     {
    34     for (i=n;i>=1;i--)
    35     {
    36         bt=bt*10%p;
    37         lst[i]=(lst[i+1]+(s[i]-'0')*bt)%p;
    38         ls[i]=lst[i];
    39     }
    40     sort(ls+1,ls+n+1);
    41     for (i=1;i<=n+1;i++)
    42     Map[ls[i]]=i;
    43     for (i=1;i<=n+1;i++)
    44     lst[i]=Map[lst[i]];
    45     for (i=1;i<=m;i++)
    46     {
    47      scanf("%lld%lld",&q[i].l,&q[i].r);
    48      q[i].r++;
    49      q[i].id=i;
    50     }
    51     sort(q+1,q+m+1,cmp);
    52     int l=1,r=0;
    53     long long cnt=0;
    54     for (i=1;i<=m;i++)
    55     {
    56       while (r<q[i].r) cnt+=ss[lst[++r]]++;
    57       while (r>q[i].r) cnt-=--ss[lst[r--]];
    58       while (l>q[i].l) cnt+=ss[lst[--l]]++;
    59       while (l<q[i].l) cnt-=--ss[lst[l++]];
    60       ans[q[i].id]=cnt;
    61     }
    62     for (i=1;i<=m;i++)
    63     printf("%lld
    ",ans[i]);
    64     }
    65     else 
    66     {
    67         for (i=1;i<=n;i++)
    68         if (!((s[i]-'0')%p))
    69         ss[i]=ss[i-1]+1,ls[i]=ls[i-1]+i;
    70         else ss[i]=ss[i-1],ls[i]=ls[i-1];
    71         for (i=1;i<=m;i++)
    72         {
    73             scanf("%lld%lld",&l,&r);
    74             printf("%lld
    ",ls[r]-ls[l-1]-(ss[r]-ss[l-1])*(l-1));
    75         }
    76     }    
    77 }
  • 相关阅读:
    史上自定义 JavaScript 函数Top 10
    switch
    (不)扩展内置原型((Not) Augmenting Built-in Prototypes)
    for-in循环(for-in Loops)
    for
    在dreamweaver中设置php服务器F12预览的方法介绍
    method
    CSS中background-image【CSS Sprites,base64编码】
    shell编程中的小问题
    常见的linux问题积累
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7670162.html
Copyright © 2011-2022 走看看