代码用时:1h
10W级的数据跑莫队比较正常吧。注意特判P==2 || P==5的情况(只需要判断个位数即可)。
WA了两次,struct D中x变量应该是long long的。
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> #define rep(i,l,r) for (int i=l; i<=r; i++) typedef long long ll; using namespace std; const int N=200100; int n,m,x,y,cnt,bl[N],num[N],c[N]; ll P,ans,res[N]; char S[N]; struct D{ ll x; int y; }s[N]; struct T{ int l,r,id; }a[N]; bool cmp(D a,D b){ return a.x<b.x; } bool cmp1(T a,T b){ return (bl[a.l]==bl[b.l]) ? a.r<b.r : bl[a.l]<bl[b.l]; } void work(int x,int k){ if (k==1) ans+=num[c[x]],num[c[x]]++; else num[c[x]]--,ans-=num[c[x]]; } void solve(){ rep(i,1,n){ s[i]=s[i-1]; if (!((S[i]-‘0‘)%P)) s[i].x+=i,s[i].y++; } while (m--) scanf("%d%d",&x,&y),printf("%lld\n",s[y].x-s[x-1].x-1ll*(x-1)*(s[y].y-s[x-1].y)); } int main(){ freopen("bzoj4542.in","r",stdin); freopen("bzoj4542.out","w",stdout); scanf("%lld",&P); scanf("%s%d",S+1,&m); n=strlen(S+1); ll now=1; if (P==2 || P==5) { solve(); return 0; } rep(i,1,m) scanf("%d%d",&a[i].l,&a[i].r),a[i].r++,a[i].id=i; for (int i=n; i; i--,now=now*10%P) s[i].x=(s[i+1].x+(S[i]-‘0‘)*now)%P,s[i].y=i; s[++n].x=0; s[n].y=n; sort(s+1,s+n+1,cmp); rep(i,1,n){ if (i==1 || s[i].x!=s[i-1].x) cnt++; c[s[i].y]=cnt; } int sz=(int)sqrt(n)+1; rep(i,1,n) bl[i]=(i-1)/sz; sort(a+1,a+m+1,cmp1); int L=1,R=1; num[c[1]]++; rep(i,1,m){ while (R<a[i].r) work(++R,1); while (L>a[i].l) work(--L,1); while (R>a[i].r) work(R--,-1); while (L<a[i].l) work(L++,-1); res[a[i].id]=ans; } rep(i,1,m) printf("%lld\n",res[i]); return 0; }