- 开始就想 (10) 进制 (hash) ,(Hash(r)equiv Hash(l-1)cdot 10^{r-l+1}) ,感觉没什么美妙的性质啊...
- 然后把 (hash) 换个方向,先加低位,再加高位,就成了 (frac {Hash(l)-Hash(r+1)} {10^{n-r}}equiv 0) ,似乎,就很美妙了?
- 当 (P
ot=2,5) 时,下面的分母有逆元,那么只能是 (Hash(l)equiv Hash(r+1)) ,就变成了在一段区间内问相同元素的对数,离散化之后,用莫队可以解决.
- 当 (P=2,5) 时,一段区间内仅有以 (P,0) 结尾的串符合条件,计数相当简单.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read()
{
int out=0,fh=1;
char jp=getchar();
while ((jp>'9'||jp<'0')&&jp!='-')
jp=getchar();
if (jp=='-')
fh=-1,jp=getchar();
while (jp>='0'&&jp<='9')
out=out*10+jp-'0',jp=getchar();
return out*fh;
}
const int MAXN=1e5+10;
int n,m,P;
inline int add(int a,int b)
{
return (a + b) % P;
}
inline int mul(int a,int b)
{
return 1LL * a * b % P;
}
struct query
{
int l,r,id,bel;
bool operator < (const query &rhs) const
{
if(bel!=rhs.bel)
return bel<rhs.bel;
if(r!=rhs.r)
return r<rhs.r;
return l<rhs.l;
}
}q[MAXN];
char buf[MAXN];
int Hash[MAXN],cp[MAXN];
int cnt[MAXN];
ll ans[MAXN],res;
void add(int x)
{
res+=cnt[Hash[x]];
++cnt[Hash[x]];
}
void rem(int x)
{
--cnt[Hash[x]];
res-=cnt[Hash[x]];
}
int sumcnt[MAXN],sumpos[MAXN];
void solve_spj()
{
for(int i=1;i<=n;++i)
{
if(buf[i]-'0'==0 || buf[i]-'0'==P)
sumcnt[i]=1,sumpos[i]=i;
sumcnt[i]+=sumcnt[i-1];
sumpos[i]+=sumpos[i-1];
}
m=read();
for(int i=1;i<=m;++i)
{
int l=read(),r=read();
ll cntsum=sumcnt[r]-sumcnt[l-1],possum=sumpos[r]-sumpos[l-1];
ll res=possum-1LL*(l-1)*cntsum;
printf("%lld
",res);
}
}
int main()
{
P=read();
scanf("%s",buf+1);
n=strlen(buf+1);
if(P==2 || P==5)
{
solve_spj();
return 0;
}
int pow10=1;
for(int i=n;i>=1;--i)
{
cp[i]=Hash[i]=add(Hash[i+1],mul(buf[i]-'0',pow10));
pow10=mul(pow10,10);
}
++n;//0
sort(cp+1,cp+1+n);
int tot=unique(cp+1,cp+1+n)-cp-1;
for(int i=1;i<=n;++i)
Hash[i]=lower_bound(cp+1,cp+1+tot,Hash[i])-cp;
m=read();
int BlockSize=sqrt(m);
for(int i=1;i<=m;++i)
{
q[i].l=read();
q[i].r=read();
q[i].id=i;
q[i].bel=q[i].l/BlockSize;
}
sort(q+1,q+1+m);
int L=1,R=0;
for(int i=1;i<=m;++i)
{
int l=q[i].l,r=q[i].r;
++r;
if(l==r)
continue;
while(R<r)
add(++R);
while(L<l)
rem(L++);
while(L>l)
add(--L);
while(R>r)
rem(R--);
ans[q[i].id]=res;
}
for(int i=1;i<=m;++i)
printf("%lld
",ans[i]);
return 0;
}