zoukankan      html  css  js  c++  java
  • bzoj 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。
     
    实现代码:
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const ll M = 1e5 + 10;
    ll blo;
    struct node{
         ll id,l,r;
         bool operator < (const node &k) const {
             if(l/blo == k.l/blo) return r < k.r;
             return l/blo < k.l/blo;
         }
    }q[M];
    ll a[M],hs[M];
    ll ba[M],ans[M];
    char s[M];
    map<ll,ll>mp;
    
    int main()
    {
        ll p,m,l=1,r=0;
        scanf("%lld%s%lld",&p,s+1,&m);
        ll n = strlen(s+1); blo = (ll)sqrt(n*1.0);
        if(p !=2 &&p != 5){
            ll num = 1;
            for(ll i = n;i >= 1;i --){
                a[i] = (a[i+1]+(s[i]-48)*num)%p;
                num = num*10%p;
                hs[i] = a[i];
            }
            sort(hs+1,hs+2+n);
            ll siz = unique(hs+1,hs+2+n)-hs-1;
            for(int i = 1;i <= n+1;i ++)
                a[i] = lower_bound(hs+1,hs+2+siz,a[i])-hs;
            for(ll i = 1;i <= m;i ++){
                scanf("%lld%lld",&q[i].l,&q[i].r);
                q[i].id = i; q[i].r ++;
            }
            sort(q+1,q+m+1);
            ll cnt = 0;
            for(ll i = 1;i <= m;i ++){
                while(r < q[i].r) cnt += ba[a[++r]]++;
                while(l > q[i].l) cnt += ba[a[--l]]++;
                while(l < q[i].l) cnt -= --ba[a[l++]];
                while(r > q[i].r) cnt -= --ba[a[r--]];
                ans[q[i].id] = cnt;
            }
            for(ll i = 1;i <= m;i ++)
                printf("%lld
    ",ans[i]);
        }
        else{
            for(ll i = 1;i <= n;i ++){
                if(!((s[i]-48)%p))
                    ba[i] = ba[i-1]+1,hs[i] = hs[i-1]+i;
                else
                    ba[i] = ba[i-1],hs[i] = hs[i-1];
            }
            for(ll i = 1;i <= m;i ++){
                scanf("%lld%lld",&l,&r);
                printf("%lld
    ",hs[r]-hs[l-1]-(ba[r]-ba[l-1])*(l-1));
            }
        }
    }
  • 相关阅读:
    TCP 连接中的TIME_WAIT
    tcp 重组原理
    自己用wireshark 抓了个包,分析了一下
    wireshark 使用技巧
    IP 网际协议
    CSS3 选择器
    ajax 底层源码解析
    初识 Java
    jQuery (DOM篇)
    绘制 SVG
  • 原文地址:https://www.cnblogs.com/kls123/p/9937197.html
Copyright © 2011-2022 走看看