Codeforces Round #778 (Div. 1 + Div. 2, based on Technocup 2022 Final Round) F Minimal String Xoration CF1654F

A-E 都还是比较简单的。

首先,容易想到的,异或上 2k,相当于以 2k+1 的长度分块,然后每一块对半切,然后交换左右部分。

我的想法是由于这个交换的性质,也许我们可以尝试着快速计算哈希值。

显然有 h(x,2k,i)=h(x,2k1,i)+h(x xor 2k1,2k1,i)h(x,k,i) 表示异或上 x,长度为 2k,左端点为 i,这个区间的哈希值。

不过你现在好像必须 O(n2) 以上取计算每个状态!

于是你考虑能否交换,使得查询区间成为前缀区间,然后我们只记录前缀区间的哈希值即可。

显然你可以写一份暴力,每次判断查询区间是否与 0 分居两侧,是的话就换。写出来后发现 x=x xor i 即可。

#pragma GCC optimize("Ofast","-funroll-loops") #pragma GCC target("sse4.1","sse4.2","ssse3","sse3","sse2","sse","avx2","avx","popcnt","tune=native") #include <bits/stdc++.h> //#define int long long #define ull unsigned long long #define pb push_back using namespace std; const ull base=19260817; const int N=(1<<18)+5; //map<int,ull>mp[N][19]; ull h[N][19]; ull v[26],pw[N]; char s[N]; int n,m,M; mt19937 RAND(time(0)); ull cal(ull x) { return x*x*x*x+2*x*x*x+3*x*x+4*x+7+M; } ull dfs(int x,int k,int i) { //i\to 0 // for(int t=1;t<=m+1;t++) { // for(int p=m;p>=0;p--) { // int l=(1<<p),r=(1<<(p+1))-1; //// if(l<=i&&(i+(1<<k)-1)<=r) { // if((i>>p)&1) { // x^=(1<<p); // i-=l; // } // } x^=i; // cout<<i<<" "<<h[x][k]<<'\n'; return h[x][k]; // } } ull get(int x,int l,int r) { int qwq=(r-l+1),nw=l; ull res=0; for(int i=m;i>=0;i--) { // cout<<nw<<" "<<res<<" "<<l<<" "<<r<<'\n'; if((qwq>>i)&1) { res=res*pw[(1<<i)]+dfs(x,i,nw); nw+=(1<<i); } } return res; // ull res=0; // for(int i=l;i<=r;i++) res=res*base+s[i^x]-'a'; // cout<<x<<" "<<l<<" "<<r<<" "<<res<<'\n'; // return res; } bool cmp(int x,int y) { int l=0,r=n-1,res=-1; while(l<=r) { int mid=(l+r)>>1; if(get(x,0,mid)==get(y,0,mid)) res=mid,l=mid+1; else r=mid-1; } if(res==n-1) return 0; ++res; // cout<<x<<" "<<y<<" "<<res<<" "<<s[res^x]<<" "<<s[res^y]<<'\n'; if(s[res^x]<s[res^y]) return 1; return 0; } signed main() { cin.tie(0); ios::sync_with_stdio(false); cin>>m>>s; n=(1<<m); M=RAND()%10; for(int i=0;i<26;i++) v[i]=cal(cal(cal(cal(cal((ull)i))))); pw[0]=1; for(int i=1;i<=n;i++) pw[i]=pw[i-1]*base; for(int i=0;i<n;i++) { // for(int j=0;j<n;j++) { // h[i][0][j]=v[s[j^i]-'a']; // } h[i][0]=v[s[i]-'a']; } for(int k=1;k<=m;k++) { int len=(1<<k); for(int x=0;x<n;x++) { // for(int i=0;i<n;i+=len) { // h[x][k][i]=h[x][k-1][i]*pw[len/2]+h[x^(1ll<<(k-1))][k-1][i]; // } h[x][k]=h[x][k-1]*pw[len/2]+h[x^(1<<(k-1))][k-1]; } } int ans=0; for(int i=1;i<n;i++) { if(cmp(i,ans)==1) // { // for(int j=0;j<=m;j++) map<int,ull>().swap(mp[ans][j]); ans=i; // } else { // for(int j=0;j<=m;j++) map<int,ull>().swap(mp[i][j]); // } } // cout<<ans<<'\n'; for(int i=0;i<n;i++) cout<<(char)(s[i^ans]); return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/16858210.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(24)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示