1. 程式人生 > >bzoj4542: [Hnoi2016]大數(莫隊)

bzoj4542: [Hnoi2016]大數(莫隊)

-a urn onclick lose 技術 font pda view stream

  這題...離散化...$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\n", ans[i]); }
View Code

bzoj4542: [Hnoi2016]大數(莫隊)