[bzoj4542][Hnoi2016]大数——同余+莫队
发布时间:2020-12-14 04:28:36 所属栏目:大数据 来源:网络整理
导读:题目大意: 给定一个质数p和一串数字序列,每次询问一个区间[L,R]中有多少个子区间表示的数为p的倍数。 思路: 首先考虑如何判断一段数字是不是p的倍数,不难想到可以用模p意义下的值来判断,但是这样最多便有可能会有 (n^2) 个余数,每一次计算也需要区间
题目大意:给定一个质数p和一串数字序列,每次询问一个区间[L,R]中有多少个子区间表示的数为p的倍数。 思路:首先考虑如何判断一段数字是不是p的倍数,不难想到可以用模p意义下的值来判断,但是这样最多便有可能会有(n^2)个余数,每一次计算也需要区间长度的时间,不太方便。 #include<bits/stdc++.h> #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i) #define DREP(i,i##_end_=b;i>=i##_end_;--i) #define MREP(i,x) for(int i=beg[x],v;v=to[i],i;i=las[i]) #define debug(x) cout<<#x<<"="<<x<<endl #define fi first #define se second #define mk make_pair #define pb push_back typedef long long ll; using namespace std; void File(){ freopen("bzoj4542.in","r",stdin); freopen("bzoj4542.out","w",stdout); } template<typename T>void read(T &_){ T __=0,mul=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')mul=-1; ch=getchar(); } while(isdigit(ch))__=(__<<1)+(__<<3)+(ch^'0'),ch=getchar(); _=__*mul; } const int maxn=1e5+10; int n,p,m,a[maxn]; char str[maxn]; namespace subtask1{ ll s1[maxn],s2[maxn]; void work(){ REP(i,1,n){ s1[i]+=s1[i-1]; s2[i]+=s2[i-1]; if(a[i]%p==0){ ++s1[i]; s2[i]+=i; } } int l,r; REP(i,m){ read(l),read(r); printf("%lldn",s2[r]-s2[l-1]-(s1[r]-s1[l-1])*(l-1)); } } } namespace subtask2{ int tot,bel[maxn]; ll sum[maxn],p10[maxn],b[maxn],ans[maxn],ton[maxn],now; struct Query{ int l,r,id; bool operator < (const Query & tt) const { if(bel[l]==bel[tt.l])return r<tt.r; return bel[l]<bel[tt.l]; } }qu[maxn]; void calc(int pos,int ty){ int w=sum[pos]; now-=ton[w]*(ton[w]-1)/2; ton[w]+=ty; now+=ton[w]*(ton[w]-1)/2; } void work(){ p10[0]=1; REP(i,n)p10[i]=p10[i-1]*10%p; ll ss=0; DREP(i,n,1){ ss=(ss+a[i]*p10[n-i])%p; sum[i]=(ss+p)%p; } REP(i,n+1)b[++tot]=sum[i]; sort(b+1,b+tot+1); tot=unique(b+1,b+tot+1)-b-1; REP(i,n+1)sum[i]=lower_bound(b+1,b+tot+1,sum[i])-b; REP(i,n)bel[i]=(i-1)/400+1; REP(i,m)read(qu[i].l),read(qu[i].r),qu[i].id=i; sort(qu+1,qu+m+1); int L=1,R=0; REP(i,m){ int l=qu[i].l,r=qu[i].r; while(L>l)calc(L-1,1),--L; while(R<r+1)calc(R+1,++R; while(L<l)calc(L,-1),++L; while(R>r+1)calc(R,--R; ans[qu[i].id]=now; } REP(i,m)printf("%lldn",ans[i]); } } int main(){ File(); read(p); scanf("%s",str+1); n=strlen(str+1); REP(i,n)a[i]=str[i]^'0'; read(m); if(p==2 || p==5)return subtask1::work(),0; else return subtask2::work(),0; return 0; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |