1. 程式人生 > >【bzoj5452】[Hnoi2016]大數(莫隊)

【bzoj5452】[Hnoi2016]大數(莫隊)

geo tchar .com sca main pan using play min

  題目傳送門: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\n",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\n",ans[i]); }
bzoj4542

【bzoj5452】[Hnoi2016]大數(莫隊)