Problem
Solution
不知道为啥,我看到这题就觉得是莫队,所以就没怎多想,就那么做了
考虑一个大数 p|A p | A ,那么显然 p|A∗10x,x∈N p | A ∗ 10 x , x ∈ N
所以可以预处理 f[i] f [ i ] 表示从第 i i 开始直到末尾所组成的大数的值,那么对于一个大数 a[l…r] a [ l … r ] 如果模 p p 为零,则,题目转化成了统计一段区间中相同的数字有多少对,那么这题就成了一个很经典的莫队问题了
接下来考虑怎么求 f[] f [ ] 数组,考虑到同余的可乘性,
设
g[x]=10xmodp
g
[
x
]
=
10
x
mod
p
则
g[x]=g[x+1]∗10modp
g
[
x
]
=
g
[
x
+
1
]
∗
10
mod
p
进而得到 f[i]=(a[i]∗g[i]+f[i+1])modp f [ i ] = ( a [ i ] ∗ g [ i ] + f [ i + 1 ] ) mod p
Tips:在 p p 为或 5 5 <script type="math/tex" id="MathJax-Element-1773">5</script>时要特判
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rg register
#define cl(x) memset(x,0,sizeof(x))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)>0?(x):(-(x)))
template <typename _Tp> inline _Tp read(_Tp&x){
rg char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
const int N=100100;
struct Query{int l,r,id;}qu[N];
char S[N];int s[N],a[N],hash[N],b[N];
ll Ans[N];
int n,m;ll p;
inline int cmp1(const Query&aa,const Query&bb){return aa.l<bb.l;}
inline int cmp2(const Query&aa,const Query&bb){return aa.r<bb.r;}
/*struct HASH{
static const int P=1234547;
int hs[P],val[P],nxt[P];
char bo[P];
HASH(){cl(val),cl(hs),cl(bo),cl(nxt);}
int * operator [] (int x){
int mo=x%P;
rg int pp=hs[x];
while(val[pp]!=x&&nxt[pp])pp=nxt[pp];
if(val[pp]==x)return li[pp];
nxt[pp]=hs[x];
}
}hash;*/
void init();
void div_block();
void Unique();
void Print();
void pre_a(){
int f=1%p;
for(rg int i=n;i;--i){
a[i]=1ll*(a[i+1]+f*s[i]%p)%p;
f=1ll*f*10%p;
}
return ;
}
void Captain_Mo(){
rg int l=1,r=0;ll ans=0;
for(rg int i=1;i<=m;++i){
++qu[i].r;
while(r<qu[i].r){++r;ans+=(hash[a[r]]++);}
while(qu[i].l<l){--l;ans+=(hash[a[l]]++);}
while(l<qu[i].l){ans-=(--hash[a[l]]);++l;}
while(qu[i].r<r){ans-=(--hash[a[r]]);--r;}
Ans[qu[i].id]=ans;
}
return ;
}
void solve_alone(){
for(rg int i=1;i<=n;++i){
Ans[i]=Ans[i-1],a[i]=a[i-1];
if(s[i]%p==0)Ans[i]+=i,++a[i];
}
for(rg int i=1;i<=m;++i)
printf("%lld\n",Ans[qu[i].r]-Ans[qu[i].l-1]-(a[qu[i].r]-a[qu[i].l-1])*(qu[i].l-1));
return ;
}
int main(){
init();if(p==2||p==5){solve_alone();return 0;}
pre_a();
div_block();
Unique();
Captain_Mo();
Print();
return 0;
}
void Print(){for(rg int i=1;i<=m;++i)printf("%lld\n",Ans[i]);return ;}
void Unique(){
for(rg int i=1;i<=n;++i)b[i]=a[i];
sort(b+1,b+n+2);
int len=unique(b+1,b+n+2)-b-1;
for(rg int i=1;i<=n;++i)
a[i]=lower_bound(b+1,b+len+1,a[i])-b-1;
return ;
}
void div_block(){
sort(qu+1,qu+m+1,cmp1);
int block=sqrt(1.0*m);
for(rg int i=1;i<=m;i+=block)
sort(qu+i,qu+min(i+block,m),cmp2);
return ;
}
void init(){
read(p);
scanf("%s",S);
for(rg int i=0;S[i];++i)
s[++n]=S[i]-'0';
read(m);
for(rg int i=1;i<=m;++i)
read(qu[i].l),read(qu[i].r),qu[i].id=i;
return ;
}