bzoj4542: [Hnoi2016]大數(莫隊)

  這題...離散化...$N$和$n$搞錯了...查了$2h$...QAQios

  考慮$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]$裏有幾個相同的後綴了。ide

  若是$p$爲$2$或$5$的話,咱們還得判斷這個數的個位是不是$2$或$5$的倍數。spa

#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\n", ans[i]);
}
View Code
相關文章
相關標籤/搜索