题意
做法
艹,这TM和莫队有个der的关系?????????
虽然总感觉他和莫队有关系,但是总想不到怎么做
事实上就是莫队
设数字为: a 1 a 2 a 3 a 4 a 5 . . . a n ‾ \overline{a_1a_2a_3a_4a_5...a_n} a1a2a3a4a5...an
设 t i t_i ti为 a i a i + 1 a i + 2 . . . a n ‾ m o d p \overline{a_ia_{i+1}a_{i+2}...a_{n}}\mod p aiai+1ai+2...anmodp的值。
这个 t t t数组可以 O ( n ) O(n) O(n)求出来。
再研究一下如果 a l a l + 1 . . . a r ‾ \overline{a_la_{l+1}...a_{r}} alal+1...ar是 p p p的倍数呢?那么不难发现 t l − t r + 1 ≡ 0 m o d p t_{l}-t_{r+1}≡0 \mod p tl−tr+1≡0modp,因为 a l a l + 1 . . . a r ‾ ≡ 0 m o d p , a l a l + 1 . . . a r ∗ 1 0 n − r ≡ 0 m o d p \overline{a_la_{l+1}...a_{r}}≡0\mod p,{a_la_{l+1}...a_{r}}*10^{n-r}≡0\mod p alal+1...ar≡0modp,alal+1...ar∗10n−r≡0modp,所以 t l ≡ t r + 1 t_{l}≡t_{r+1} tl≡tr+1。
但是是不是 t l ≡ t r + 1 t_{l}≡t_{r+1} tl≡tr+1,那么 a l a l + 1 . . . a r ‾ ≡ 0 m o d p \overline{a_la_{l+1}...a_{r}}≡0\mod p alal+1...ar≡0modp,首先我们知道 a l a l + 1 . . . a r ∗ 1 0 n − r ≡ 0 m o d p {a_la_{l+1}...a_{r}}*10^{n-r}≡0\mod p alal+1...ar∗10n−r≡0modp,如果 g c d ( 1 0 n − r , p ) = 1 gcd(10^{n-r},p)=1 gcd(10n−r,p)=1,那么这个是绝对成立的,但是如果 g c d ( 1 0 n − r , p ) ≠ 1 gcd(10^{n-r},p)≠1 gcd(10n−r,p)=1,则不一定成立,此时 p = 2 , 5 p=2,5 p=2,5,那么对于这两种情况,暴力判断如果这个位置能被整除,那么以这个位置作为 r r r的区间一定能被整除。
对于 p ≠ 2 , 5 p≠2,5 p=2,5的情况,就是维护 [ l , r + 1 ] [l,r+1] [l,r+1]区间中 t t t数组的相等对数,直接莫队 O ( n n ) O(n\sqrt{n}) O(nn)暴力上就行了,别忘了 t t t数组离散化哦。
时间复杂度: O ( n n ) O(n\sqrt{n}) O(nn)。
#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\n",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\n",anslist[i]);
}
return 0;
}