在做 P11267 这题时,如果你 WA 过那你大概能发现当 $S=0^n$ 时,每次询问得到的结果为 $s+k$,其原理也不难推理。
$s+k$ 是什么?是我们的 A+B Problem 啊!
因此我们将正解稍作修改后就能得到 A+B Problem 的 AC 代码了!不过需要注意的一点是,A+B Problem 中 a,b 可能为负数,我们还需要根据 a,b 的正负做点特判,a=0 情况也需要特殊处理。
于是我们在原代码的基础上得到了以下 AC 代码:
#include<bits/stdc++.h> using namespace std; using ll=long long; using vi=vector<int>; using vl=vector<ll>; const ll inf=0x3f3f3f3f3f3f3f3f; const int KMAX=62; int main(){ cin.tie(0)->sync_with_stdio(0); ll n=3,q=1; ll m=141445; // cin>>n>>m>>q; string S="000"; // cin>>S; vector<vi>zu(64,vi(n,-1)); vector<vl>zujl(64,vl(n)); vl sc(n); int x=m%n; ll r=n+m-1; sc[0]=0; bool sfy1=false; for(int i=1,x;i<n*2;++i){ x=i%n; if(S[x]=='1')sc[x]=0,sfy1=true; else sc[x]=sc[(i-1+n)%n]+1; } if(sfy1==false)for(auto &v:sc)v=inf; for(int i=n*2-1-x,u,v;i>=0;--i){ if(r>(ll)i+m)r=m+i; if((r-sc[r%n])>i)r-=sc[r%n]; else r=i+1; u=i%n,v=r%n; zu[0][u]=v; zujl[0][u]=((ll)r-(ll)i); } function<void(int,int)>dfs=[&](int u,int x){ int fa=zu[x-1][u]; zu[x][u]=zu[x-1][fa]; zujl[x][u]=(zujl[x-1][u]+zujl[x-1][fa]); if(zu[x][zu[0][u]]==-1)dfs(zu[0][u],x); }; for(int i=0;i<n;i++){ if(zu[KMAX][i]==-1){ for(int j=1;j<=KMAX;++j)dfs(i,j); } } while(q--){ int s,k; cin>>s>>k; int a=abs(s),b=abs(k); if(a==0){//需要特判 cout<<k<<endl; continue; } int x=1; if(s<0&&k>0||s>0&&k<0){//两数中只有一数为负 x=-1; } int p=(a-1)%n; ll ans=a; // cout<<a<<" "<<b<<" "<<x<<endl; for(ll i=KMAX;i>=0;--i){ // cout<<ans<<endl; if(b>=(1ll<<i)){ ans=(ans+x*zujl[i][p]); p=zu[i][p]; b-=(1ll<<i); } } if(s<0&&k>0||s<0&&k<0)ans=-ans; cout<<ans<<endl; } return 0; }
当然还能更快,但是我懒了。