【題解】CF1320D Reachable Strings
阿新 • • 發佈:2021-10-04
\(\text{Solution:}\)
先來發現操作的性質,發現其本質是一個對 \(0\) 進行的位移,而且位移前後 \(0\) 位置的奇偶性不變。
那麼,我們發現,如果一個子串能變成另外一個,當且僅當其 \(0\) 組成的部位構造相同、奇偶性相同。
所以這也就啟發我們直接對 \(0\) 的位置進行雜湊。所以考慮直接在原串上,只對 \(0\) 的位置以奇偶性為值來雜湊。
判斷的時候對開頭的奇偶性分一下類即可。
注意雜湊的寫法要規範:以後就用倒著的。
for(){ hash[i]=hash[i-1]*base+v[i] } query(){return (hash[r]-hash[l-1]*pw[r-l+1]);}
程式碼:
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; const int hmod=1004535809; const int base=23; int h[N][2],a[N],n,m,c[N]; int pw[N],inv[N],cnt[N]; char s[N]; inline int Add(int x,int y,int M=hmod){return (x+y)%M;} inline int Mul(int x,int y,int M=hmod){return 1ll*x*y%M;} inline int Dec(int x,int y,int M=hmod){return (x-y+M)%M;} inline int qpow(int x,int y,int M=hmod){ int res=1; while(y){ if(y&1)res=Mul(res,x,M); x=Mul(x,x,M);y>>=1; } return res; } inline int read(){ int s=0,w=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')w=-1; ch=getchar(); } while(isdigit(ch)){ s=s*10+ch-'0'; ch=getchar(); } return s*w; } int query(int l,int r){ int opt=l&1; int R=Dec(h[r][opt],Mul(h[l-1][opt],pw[cnt[r]-cnt[l-1]])); return R; } int main(){ freopen("in.txt","r",stdin); n=read(); scanf("%s",s+1); for(int i=1;i<=n;++i)a[i]=s[i]-'0'; pw[0]=1; for(int i=1;i<=n+1;++i)pw[i]=Mul(pw[i-1],base); inv[n+1]=qpow(pw[n+1],hmod-2); for(int i=n+1;i;--i)inv[i-1]=Mul(inv[i],base); h[0][0]=h[0][1]=1; for(int i=1;i<=n;++i){ cnt[i]=cnt[i-1]+(a[i]==0); if(a[i]==1){ h[i][0]=h[i-1][0]; h[i][1]=h[i-1][1]; continue; } cnt[i]=cnt[i-1]+1; int v=i&1; h[i][0]=Add(Mul(h[i-1][0],base),v+1); h[i][1]=Add(Mul(h[i-1][1],base),(v^1)+1); } m=read(); while(m--){ int l=read(),r=read(),len=read(); if(query(l,l+len-1)==query(r,r+len-1))puts("Yes"); else puts("No"); } return 0; }