zoukankan      html  css  js  c++  java
  • bzoj4542 大数

    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个询问的答案。

    可以考虑用莫队解决区间询问
    对于p!=2且p!=5,预处理串的每个后缀mod p的值,若两后缀mod p相等则它们间的一段mod p=0
    若p=2或5,则一个串mod p为0当且仅当末尾能被p整除
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    typedef long long lint;
    lint Ans=0;
    int m;
    char s[100005];
    struct Q{
        int l,r,id;
    }q[100005];
    lint ans[100005];
    int b,l,p;
    int mp[100005],id[100005];
    inline bool operator<(const Q&a,const Q&b){
        if(id[a.l]!=id[b.l])return id[a.l]<id[b.l];
        return (a.r<b.r)!=(id[a.l]&1);
    }
    namespace map{
        const int P=1234577;
        lint xs[P];
        int ys[P],now=0;
        bool d[P];
        int get(lint x){
            int w=x%P;
            while(d[w]){
                if(xs[w]==x)return ys[w];
                w+=1237;
                if(w>=P)w-=P;
            }
            d[w]=1;xs[w]=x;
            return ys[w]=now++;
        }
    }
    int yv[100005];
    inline void inc(int x){
        Ans+=yv[x]++;
    }
    inline void dec(int x){
        Ans-=--yv[x];
    }
    int main(){
        scanf("%d%s%d",&p,s+1,&m);
        l=strlen(s+1);
        b=double(l+1)/(sqrt(m+1)+1)+1;
        for(int i=1;i<=l;i++)id[i]=(i-1)/b;
        for(int i=0;i<m;i++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id=i;
        }
        std::sort(q,q+m);
        int p10=1;
        if(p!=2&&p!=5){
            for(int i=l;i;i--){
                mp[i]=(mp[i+1]+(s[i]-48ll)*p10)%p;
                p10=p10*10ll%p;
            }
            for(int i=1;i<=l+1;i++)mp[i]=map::get(mp[i]);
        }else for(int i=1;i<=l;i++)mp[i]=(s[i]-48)%p;
        int L=1,R=0;
        if(p!=2&&p!=5)
        for(int i=0;i<m;i++){
            int l=q[i].l,r=q[i].r+1;
            while(L<l)dec(mp[L++]);
            while(L>l)inc(mp[--L]);
            while(R<r)inc(mp[++R]);
            while(R>r)dec(mp[R--]);
            ans[q[i].id]=Ans;
        }else for(int i=0,c=0;i<m;i++){
            int l=q[i].l,r=q[i].r;
            while(L<l){
                Ans-=c;
                if(!mp[L++])--c;
            }
            while(L>l){
                if(!mp[--L])++c;
                Ans+=c;
            }
            while(R<r){
                if(!mp[++R])++c,Ans+=R-L+1;
            }
            while(R>r){
                if(!mp[R--])Ans-=R-L+2,--c;
            }
            ans[q[i].id]=Ans;
        }
        for(int i=0;i<m;i++)printf("%lld
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    为什么构造函数不能声明为虚函数,析构函数可以
    _stdcall,_cdecl区别
    C++的dllexport和dllimport
    什么样的代码才是好代码
    苦逼三流小公司程序员这半年找工作经历(3)——选择offer
    c# DataTable、DataSet、DataReader
    C# 定时器
    sql 中如何将返回的记录某一条置顶
    c# devExpress控件 comboBoxEdit,gridControl1,labelcontrol、xtraReports ,ButtonEdit,dateEdit
    c# 公共方法
  • 原文地址:https://www.cnblogs.com/ccz181078/p/5414625.html
Copyright © 2011-2022 走看看