题意
做法
艹,这TM和莫队有个der的关系?????????
虽然总感觉他和莫队有关系,但是总想不到怎么做
事实上就是莫队
设数字为:(overline{a_1a_2a_3a_4a_5...a_n})
设(t_i)为(overline{a_ia_{i+1}a_{i+2}...a_{n}}mod p)的值。
这个(t)数组可以(O(n))求出来。
再研究一下如果(overline{a_la_{l+1}...a_{r}})是(p)的倍数呢?那么不难发现(t_{l}-t_{r+1}≡0 mod p),因为(overline{a_la_{l+1}...a_{r}}≡0mod p,{a_la_{l+1}...a_{r}}*10^{n-r}≡0mod p),所以(t_{l}≡t_{r+1})。
但是是不是(t_{l}≡t_{r+1}),那么(overline{a_la_{l+1}...a_{r}}≡0mod p),首先我们知道({a_la_{l+1}...a_{r}}*10^{n-r}≡0mod p),如果(gcd(10^{n-r},p)=1),那么这个是绝对成立的,但是如果(gcd(10^{n-r},p)≠1),则不一定成立,此时(p=2,5),那么对于这两种情况,暴力判断如果这个位置能被整除,那么以这个位置作为(r)的区间一定能被整除。
对于(p≠2,5)的情况,就是维护([l,r+1])区间中(t)数组的相等对数,直接莫队(O(nsqrt{n}))暴力上就行了,别忘了(t)数组离散化哦。
时间复杂度:(O(nsqrt{n}))。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 110000
using namespace std;
typedef long long LL;
char st[N];
LL a[N];
LL n,p,m;
LL f1[N];LL f2[N];//2或者5的情况
LL belong[N],block;//分块
LL si[N],id[N],be[N],cnt;//离散化
LL tot[N];
LL ans;//移动的ans
struct query
{
LL l,r,id;
}q[N];LL anslist[N];
inline bool cmp1(LL x,LL y){return si[x]<si[y];}
inline bool cmp2(query x,query y){return be[x.l]!=be[y.l]?x.l<y.l:x.r<y.r;}
inline void add(LL x){ans+=tot[x];tot[x]++;}
inline void del(LL x){tot[x]--;ans-=tot[x];}
int main()
{
scanf("%lld",&p);
scanf("%s",st+1);n=strlen(st+1);
for(LL i=1;i<=n;i++)a[i]=st[i]-'0';
if(p==2 || p==5)
{
for(LL i=1;i<=n;i++)
{
if(a[i]%p==0)f1[i]++,f2[i]+=i;
f1[i]+=f1[i-1],f2[i]+=f2[i-1];
}
scanf("%lld",&m);
for(LL i=1;i<=m;i++)
{
LL l,r;scanf("%lld%lld",&l,&r);
LL x1=f1[r]-f1[l-1];LL x2=f2[r]-f2[l-1];
printf("%lld
",x2-(LL)x1*(l-1));
}
}
else
{
LL mo=1;
for(LL i=n;i>=1;i--)si[i]=(si[i+1]+mo*a[i])%p,mo=(mo*10)%p,id[i]=i;
si[++n]=0;id[n]=n;
sort(id+1,id+n+1,cmp1);
for(LL i=1;i<=n;i++)
{
if(i==1 || be[cnt]!=si[id[i]])cnt++,be[cnt]=si[id[i]];
si[id[i]]=cnt;
}
block=sqrt(n);
for(LL i=1;i<=n;i++)be[i]=(i-1)/block+1;
scanf("%lld",&m);
for(LL i=1;i<=m;i++){scanf("%lld%lld",&q[i].l,&q[i].r);q[i].id=i;}
sort(q+1,q+m+1,cmp2);
LL l=1,r=0;
for(LL i=1;i<=m;i++)
{
q[i].r++;
while(r<q[i].r)add(si[r+1]),r++;
while(l>q[i].l)add(si[l-1]),l--;
while(r>q[i].r)del(si[r]),r--;
while(l<q[i].l)del(si[l]),l++;
anslist[q[i].id]=ans;
}
for(LL i=1;i<=m;i++)printf("%lld
",anslist[i]);
}
return 0;
}