zoukankan      html  css  js  c++  java
  • bzoj4542: [Hnoi2016]大数(莫队)

      这题...离散化...$N$和$n$搞错了...查了$2h$...QAQ

      考虑$s[l...r]$,可以由两个后缀$suf[l]-suf[r+1]$得到$s[l...r]$代表的数乘$10^k$得到的结果,如果$p$不为$2$或$5$,即$gcd(p, 10^k)=1$,那么显然$s[l...r]$乘$10^k$模$p$为$0$的话,$s[l...r]$模p也为$0$,所以我们就可以变成询问$[l,r+1]$里有几个相同的后缀了。

      如果$p$为$2$或$5$的话,我们还得判断这个数的个位是否是$2$或$5$的倍数。

    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int maxn=500010, inf=1e9;
    struct poi{int l, r, pos;}q[maxn];
    int n, N, m, blo;
    int bl[maxn], cnt[maxn], cnt2[maxn], b[maxn], sum[maxn];
    ll p, ANS;
    ll ans[maxn], mi[maxn];
    char s[maxn];
    inline void read(int &k)
    {
        int f=1; k=0; char c=getchar();
        while(c<'0' || c>'9') c=='-'&&(f=-1), c=getchar();
        while(c<='9' && c>='0') k=k*10+c-'0', c=getchar();
        k*=f;    
    } 
    bool operator < (poi a, poi b)
    {return bl[a.l]<bl[b.l] || (bl[a.l]==bl[b.l] && ((bl[a.l]&1)?a.r<b.r:a.r>b.r));} 
    inline void update(int x, int delta, int ty)
    {
        if(delta==1)
        {
            ANS+=(!ty || p>10 || (s[x-1]-'0')%p==0)*delta*(ty?cnt[sum[x]]:cnt2[sum[x]]);
            cnt[sum[x]]+=delta;
            cnt2[sum[x]]+=(p>10 || (s[x-1]-'0')%p==0)*delta;
        }
        else
        {
            cnt[sum[x]]+=delta;
            cnt2[sum[x]]+=(p>10 || (s[x-1]-'0')%p==0)*delta;
            ANS+=(!ty || p>10 || (s[x-1]-'0')%p==0)*delta*(ty?cnt[sum[x]]:cnt2[sum[x]]);
        }
    }
    int main()
    {
        scanf("%lld", &p); scanf("%s", s+1); n=strlen(s+1);
        blo=sqrt(n); for(int i=1;i<=n;i++) bl[i]=(i-1)/blo+1;
        mi[0]=1; for(int i=1;i<=n;i++) mi[i]=mi[i-1]*10%p;
        for(int i=n;i;i--) sum[i]=(sum[i+1]+mi[n-i]*(s[i]-'0'))%p, b[i]=sum[i]; N=n; b[++N]=0;
        sort(b+1, b+1+N); N=unique(b+1, b+1+N)-b-1;
        for(int i=1;i<=n+1;i++) sum[i]=lower_bound(b+1, b+1+N, sum[i])-b;
        read(m);
        for(int i=1;i<=m;i++) read(q[i].l), read(q[i].r), q[i].r++, q[i].pos=i;
        sort(q+1, q+1+m);
        for(int i=1, l=1, r=0;i<=m;i++)
        {
            while(l<q[i].l) update(l++, -1, 0);
            while(l>q[i].l) update(--l, 1, 0);
            while(r<q[i].r) update(++r, 1, 1);
            while(r>q[i].r) update(r--, -1, 1);
            ans[q[i].pos]=ANS;
        }
        for(int i=1;i<=m;i++) printf("%lld
    ", ans[i]);
    }
    View Code
  • 相关阅读:
    洛谷 P1939 矩阵加速(数列)
    【模板】矩阵快速幂
    洛谷 P3128 [USACO15DEC]最大流Max Flow
    洛谷 P1967 货车运输
    【模板】最近公共祖先(LCA)
    【模板】高斯消元法
    java从基础知识(七)java集合
    java基础知识(六)日期处理
    java基础知识(五)java类
    会员体系-系统豆的获取与消费
  • 原文地址:https://www.cnblogs.com/Sakits/p/8447506.html
Copyright © 2011-2022 走看看