我们考虑怎样的一个大数能够整除质数p:
当然是这个大数每一位乘上10的多少次幂
那求一个前缀的和呢?就是每一位乘上10的多少次幂的前缀和
如何判断一个区间模p是否等于0?只需要判断位置
l
l
l和位置
r
r
r的前缀和模p的值是否相等
那这就是个莫队板子题了
注意特判p=2和5的情况,具体怎么判详见此文
Code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
return res*f;
}
const int N=1e5+5;
int mod;
inline int add(int x,int y){x+=y;if(x>=mod) x-=mod;return x;}
inline int dec(int x,int y){x-=y;if(x<0) x+=mod;return x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline void inc(int &x,int y){x+=y;if(x>=mod) x-=mod;}
inline int ksm(int a,int b){int res=1;for(;b;b>>=1,a=mul(a,a)) if(b&1) res=mul(res,a);return res;}
struct Q{
int l,r,id,bl;
friend inline bool operator <(const Q &a,const Q &b){if(a.bl==b.bl) return a.r<b.r;return a.bl<b.bl;}
}q[N];
int sqr=320;
int tong[N],n,m;
char s[N];
int a[N],sum[N],b[N],fans[N],num2[N];
ll num[N];
int main(){
mod=read();scanf("%s",s);n=strlen(s);
for(int i=1;i<=n;i++) a[i]=s[i-1]-'0';
if(mod==5){
for(int i=1;i<=n;i++) num[i]=num[i-1],num2[i]=num2[i-1],num[i]+=i*(a[i]==0 || a[i]==5),num2[i]+=(a[i]==0 || a[i]==5);
m=read();
for(int l,r,i=1;i<=m;i++){
l=read(),r=read();
cout<<(num[r]-num[l-1])-1ll*(l-1)*(num2[r]-num2[l-1])<<"\n";
}
return 0;
}
if(mod==2){
for(int i=1;i<=n;i++) num[i]=num[i-1],num2[i]=num2[i-1],num[i]+=i*((a[i]&1)^1),num2[i]+=((a[i]&1)^1);
m=read();
for(int l,r,i=1;i<=m;i++){
l=read(),r=read();
cout<<(num[r]-num[l-1])-1ll*(l-1)*(num2[r]-num2[l-1])<<"\n";
}
return 0;
}
++n;int cnt=0;
for(int i=n;i;i--){
a[i]=mul(a[i],ksm(10,n-i));
inc(a[i],a[i+1]);
b[++cnt]=a[i];
}
sort(b+1,b+cnt+1);
cnt=unique(b+1,b+cnt+1)-b-1;
for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+cnt+1,a[i])-b;
int m=read();
for(int i=1;i<=m;i++){
q[i].l=read(),q[i].r=read()+1,q[i].id=i;
q[i].bl=(q[i].l-1)/sqr+1;
}
sort(q+1,q+m+1);
int l=1,r=0,ans=0;
for(int i=1;i<=m;i++){
int ql=q[i].l,qr=q[i].r;
while(l>ql) --l,++tong[a[l]],ans+=tong[a[l]]-1;
while(r<qr) ++r,++tong[a[r]],ans+=tong[a[r]]-1;
while(l<ql) ans-=tong[a[l]]-1,--tong[a[l]],++l;
while(r>qr) ans-=tong[a[r]]-1,--tong[a[r]],--r;
fans[q[i].id]=ans;
}
for(int i=1;i<=m;i++) cout<<fans[i]<<"\n";
return 0;
}