BZOJ4542: [Hnoi2016]大数
莫队·乱搞
题解:
蛤~我这种蒟蒻怎么可能自己想出来呢2333~
但是我看网上的题解很多没有证明过程,就写一下吧~
ans=∑i=lr∑j=ir1((10′)n−r∑k=ijs[i]∗10n−kmodp==0)
设num[i]=∑jk=is[i]∗10n−k
因为p是素数,那么10′=10p−2
原式:
ans=∑i=lr∑j=ir1(10(p−2)(n−r)(num[i]−num[j+1])modp==0)
如果p!=2&&p!=5,10tmodp肯定不为0。所以要想modp==0,则必有num[i]=num[j+1].
这样就转化成了一个区间中有多少对数相同,离散化一下,用莫队就可以了。
那么假如p==2||p==5呢?
我们发现一个数只要最后一位是2或5的倍数,不管前面是什么,它一定是。因此只考虑最后一位。
做两个前缀和,一个(A)记录前缀[1,i]中有多少子串是p的倍数,另一个(B)记录前缀[1,i]中有多少位是p的倍数。
ans=(A[r]−A[l−1])−(B[r]−B[l−1])∗(l−1)
(B[r]−B[l−1])∗(l−1)就是开始在l前面,结束在[l,r]中的p的倍数子串的个数。
好神啊QwQ……
Code:
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#define D(x) cout<<#x<<" = "<<x<<" "
#define E cout<<endl
using namespace std;
typedef long long ll;
const int N = 100005;
ll p,n,m,res,bsz; char str[N];
ll cnt[N],num[N],tp[N],ans[N],A[N],B[N];
struct Que{
ll l,r,id;
bool operator < (const Que &b) const {
return l/bsz < b.l/bsz || (l/bsz == b.l/bsz && r < b.r);
}
} q[N];
void insert(ll x){ res+=cnt[x]; cnt[x]++; }
void erase(ll x){ cnt[x]--; res-=cnt[x]; }
int main(){
freopen("a.in","r",stdin);
scanf("%lld%s%lld",&p,str+1,&m);
n=strlen(str+1);
if(p!=2 && p!=5){
ll base=1;
for(ll i=n;i>=1;i--){
base=base*10%p;
num[i]=(num[i+1]+(str[i]-'0')*base)%p;
tp[i]=num[i];
} tp[n+1]=num[n+1];
sort(tp+1,tp+2+n); ll tpsz=unique(tp+1,tp+2+n)-tp-1;
for(ll i=1;i<=n+1;i++){
num[i]=lower_bound(tp+1,tp+1+tpsz,num[i])-tp;
}
bsz=sqrt(n);
for(ll i=1;i<=m;i++){
scanf("%lld%lld",&q[i].l,&q[i].r);
q[i].id=i; q[i].r++;
}
sort(q+1,q+1+m);
ll lpos=1, rpos=0;
for(ll i=1;i<=m;i++){
while(lpos < q[i].l){ erase(num[lpos]); lpos++; }
while(lpos > q[i].l){ lpos--; insert(num[lpos]); }
while(rpos < q[i].r){ rpos++; insert(num[rpos]); }
while(rpos > q[i].r){ erase(num[rpos]); rpos--; }
ans[q[i].id]=res;
}
for(ll i=1;i<=m;i++) printf("%lld\n",ans[i]);
}
else{
for(ll i=1;i<=n;i++){
if((str[i]-'0')%p==0){ A[i]=A[i-1]+i; B[i]=B[i-1]+1; }
else{ A[i]=A[i-1]; B[i]=B[i-1]; }
}
ll l,r;
for(ll i=1;i<=m;i++){
scanf("%lld%lld",&l,&r);
printf("%lld\n",(A[r]-A[l-1])-(B[r]-B[l-1])*(l-1));
}
}
}