bzoj5452[Hnoi2016]大数(莫队)
Posted quzhizhou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj5452[Hnoi2016]大数(莫队)相关的知识,希望对你有一定的参考价值。
题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=4542
首先若p=2,5则这题就是道傻逼题,前缀和搞一下没了。如果p为其他质数,那么可以这么处理:
我们先预处理出数组num[i]表示原串第i~n位表示的数模p的余数,那么第l~r位表示的数模p的余数为(num[l]-num[r+1])/10^(n-r),因为10^(n-r)与p互质,所以若num[l]=num[r+1],则第l~r位表示的数是p的倍数。于是莫队一下就好了。
代码:
#include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<ctime> #include<string> #include<iostream> #include<algorithm> #include<queue> #include<vector> #include<map> #define ll long long #define ull unsigned long long #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define lowbit(x) (x& -x) #define mod 1000000007 #define inf 0x3f3f3f3f #define eps 1e-18 #define maxn 2000010 inline ll read(){ll tmp=0; char c=getchar(),f=1; for(;c<‘0‘||‘9‘<c;c=getchar())if(c==‘-‘)f=-1; for(;‘0‘<=c&&c<=‘9‘;c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-‘0‘; return tmp*f;} inline ll power(ll a,ll b){ll ans=1; for(;b;b>>=1){if(b&1)ans=ans*a%mod; a=a*a%mod;} return ans;} inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} inline void swap(int &a,int &b){int tmp=a; a=b; b=tmp;} using namespace std; struct data{ int l,r,id; }a[100010]; struct data2{ ll val; int id; }x[100010]; char s[100010]; ll rk[100010],cnt[100010],ans[100010],sum1[100010],sum2[100010]; int n,m,size; ll p,tot; bool cmp(data a,data b){return a.l/size!=b.l/size?a.l/size<b.l/size:a.r<b.r;} bool cmp2(data2 a,data2 b){return a.val<b.val;} int main() { p=read(); scanf("%s",s); n=strlen(s); size=sqrt(n); m=read(); if(p==2||p==5){ sum1[0]=sum2[0]=0; for(int i=1;i<=n;i++){ sum1[i]=sum1[i-1]; sum2[i]=sum2[i-1]; if((s[i-1]-‘0‘)%p==0)++sum1[i],sum2[i]+=i; } for(int i=1;i<=m;i++){ int l=read(),r=read(); printf("%lld ",sum2[r]-sum2[l-1]-(sum1[r]-sum1[l-1])*(l-1)); } fclose(stdin); fclose(stdout); return 0; } for(int i=1;i<=m;i++) a[i].l=read()-1,a[i].r=read(),a[i].id=i; sort(a+1,a+m+1,cmp); ll tmp=1; x[n].val=0; x[n].id=n; for(int i=n-1;i>=0;i--,tmp=tmp*10%p)x[i].val=(x[i+1].val+(s[i]-‘0‘)*tmp)%p,x[i].id=i; sort(x,x+n+1,cmp2); rk[x[0].id]=0; for(int i=1;i<=n;i++) if(x[i].val==x[i-1].val)rk[x[i].id]=rk[x[i-1].id]; else rk[x[i].id]=i; tot=0; for(int i=a[1].l;i<=a[1].r;i++) tot+=cnt[rk[i]]++; ans[a[1].id]=tot; for(int i=2;i<=m;i++){ if(a[i-1].l<a[i].l){ for(int j=a[i-1].l;j<a[i].l;j++) tot-=--cnt[rk[j]]; } else{ for(int j=a[i].l;j<a[i-1].l;j++) tot+=cnt[rk[j]]++; } if(a[i-1].r<a[i].r){ for(int j=a[i-1].r+1;j<=a[i].r;j++) tot+=cnt[rk[j]]++; } else{ for(int j=a[i].r+1;j<=a[i-1].r;j++) tot-=--cnt[rk[j]]; } ans[a[i].id]=tot; } for(int i=1;i<=m;i++) printf("%lld ",ans[i]); }
以上是关于bzoj5452[Hnoi2016]大数(莫队)的主要内容,如果未能解决你的问题,请参考以下文章