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

    传送门

    (HNOI2019)前最后一题了qwq

    这题要分情况,如果(p=2)(5),那么只要区间内最后一个数字是(p)的倍数就好了,这个可以莫队,也有更优秀的做法.莫队做法可以看代码

    否则,考虑一个数怎么表示,记(s_i)为前(i)为构成的数,可以知道区间([i,j])的数应该是(s_r-s_{l-1}*10^{r-l+1}),现在要求这个数模(p)为0,那么也就是$$s_r-s_{l-1}*10^{r-l+1}equiv0 (mathrm{mod} p)$$

    两边同时除掉(10^r),得到

    [s_r*10^{-r}-s_{l-1}*10^{-(l-1)}equiv0 (mathrm{mod} p) ]

    如果位置(i)的权值为(s_i*10^{-i}),那么一个区间([i,j])的答案就是([i-1,j])中每种权值相同的点对个数,这个还是比较好写的

    #include<bits/stdc++.h>
    #define LL long long
    #define db long double
    #define il inline
    
    using namespace std;
    const int N=1e5+10;
    il LL rd()
    {
        LL x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9') {if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*w;
    }
    int p,a[N],n,sqt,q,be[N];
    LL an[N],na;
    char cc[N];
    struct qu
    {
        int l,r,i;
        bool operator < (const qu &bb) const {return be[l]!=be[bb.l]?l<bb.l:r<bb.r;}
    }qq[N];
    int fpow(int a,int b){a%=p;int an=1;while(b){if(b&1) an=1ll*an*a%p;a=1ll*a*a%p,b>>=1;} return an;}
    namespace ct1
    {
        int cn;
        void wk()
        {
            sort(qq+1,qq+q+1);
            for(int i=1,l=1,r=0;i<=q;++i)
            {
                while(r<qq[i].r) ++r,cn+=a[r]%p==0,na+=(a[r]%p==0?r-l+1:0);
                while(r>qq[i].r) na-=(a[r]%p==0?r-l+1:0),cn-=a[r]%p==0,--r;
                while(l<qq[i].l) na-=cn,cn-=a[l]%p==0,++l;
                while(l>qq[i].l) --l,cn+=a[l]%p==0,na+=cn;
                an[qq[i].i]=na;
            }
        }
    }
    namespace ct2
    {
        int cn[N],b[N],m;
        void wk()
        {
            int pp=fpow(10,p-2);
            b[++m]=0;
            for(int i=1,j=1,sm=0;i<=n;++i)
            {
                sm=1ll*sm*10%p+a[i],j=1ll*j*pp%p;
                a[i]=1ll*sm*j%p;
                b[++m]=a[i];
            }
            sort(b+1,b+m+1),m=unique(b+1,b+m+1)-b-1;
            for(int i=0;i<=n;++i) a[i]=lower_bound(b+1,b+m+1,a[i])-b;
            for(int i=1;i<=q;++i) --qq[i].l;
            sort(qq+1,qq+q+1);
            for(int i=1,l=0,r=-1;i<=q;++i)
            {
                while(r<qq[i].r) ++r,++cn[a[r]],na+=cn[a[r]]-1;
                while(r>qq[i].r) na-=cn[a[r]]-1,--cn[a[r]],--r;
                while(l<qq[i].l) na-=cn[a[l]]-1,--cn[a[l]],++l;
                while(l>qq[i].l) --l,++cn[a[l]],na+=cn[a[l]]-1;
                an[qq[i].i]=na;
            }
        }
    }
        
    int main()
    {
        p=rd();
        scanf("%s",cc+1);
        n=strlen(cc+1);
        sqt=sqrt(n);
        for(int i=1;i<=n;++i) a[i]=cc[i]-'0',be[i]=i/sqt;
        q=rd();
        for(int i=1;i<=q;++i) qq[i].l=rd(),qq[i].r=rd(),qq[i].i=i;
        if(p==2||p==5) ct1::wk();
        else ct2::wk();
        for(int i=1;i<=q;++i) printf("%lld
    ",an[i]);
        return 0; 
    }
    
  • 相关阅读:
    关于unsigned char的取反操作
    Windows10 添加永久路由
    mysql入门-触发器
    mysql入门-视图
    Mysql入门-索引
    Mysql入门-表操作
    mysql数据类型选取
    MQ-基本操作
    关于Hadoop集群的配置方法——另附安装网址
    关于——This is probably not a problem with npm. There is likely additional logging output above.——的解决方法
  • 原文地址:https://www.cnblogs.com/smyjr/p/10659752.html
Copyright © 2011-2022 走看看