Problem
Solution
不知道爲啥,我看到這題就覺得是莫隊,所以就沒怎多想,就那麼做了
考慮一個大數 ,那麼顯然
所以可以預處理 表示從第 開始直到末尾所組成的大數 的值,那麼對於一個大數 如果模 爲零,則 ,題目轉化成了統計一段區間中相同的數字有多少對,那麼這題就成了一個很經典的莫隊問題了
接下來考慮怎麼求 數組,考慮到同餘的可乘性,
設
則
進而得到
Tips:在 爲 或 時要特判
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 ;
}