傳送門
文章目錄
題意:
思路:
一個顯然的思路就是2302^{30}230枚舉所有的xxx,讓后再檢查,這個復雜度顯然不能接受。
又發現對于每個位置它取多少不受其他位置限制,滿足可拼接性,所以我們考慮用折半搜索來搜出來前151515位的所有情況,讓后再枚舉后151515位的所有情況,讓后從另一半取出來需要的信息即可。
實現還是比較有技巧的,前151515位搜出來的情況可以用mapmapmap存一下,讓后后151515位搜出來之后,我們可以枚舉它的總長度,讓后就可以算出來還需要多少,查詢是否在mapmapmap中有即可。
當然我們也可以省去枚舉長度的一部分,只需要將我們的前151515位的數組都減去一個公共長度,后151515位的數組用最長長度減去原本長度就是我們需要的長度了,說的可能不清楚,具體細節看代碼吧,跑的倒是蠻快的。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#include<random>
#include<cassert>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid ((tr[u].l+tr[u].r)>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std
;
typedef long long LL
;
typedef unsigned long long ULL
;
typedef pair
<int,int> PII
;const int N
=1000010,mod
=1e9+7,INF
=0x3f3f3f3f;
const double eps
=1e-6;int n
;
int a
[N
];
map
<vector
<int>,int>mp
;
vector
<int>v
;
int ans
=-1;void dfs1(int u
,int sum
) {if(u
==15) {v
.clear();int mi
=INF
;for(int i
=1;i
<=n
;i
++) {int now
=a
[i
]&((1<<15)-1);now
^=sum
;v
.pb(__builtin_popcount(now
));mi
=min(mi
,__builtin_popcount(now
));}for(auto &x
:v
) x
-=mi
;mp
[v
]=sum
;return;}dfs1(u
+1,sum
+(1<<u
));dfs1(u
+1,sum
);
}void dfs2(int u
,int sum
) {if(ans
!=-1) return;if(u
==30) {v
.clear();int mx
=0;for(int i
=1;i
<=n
;i
++) {int now
=a
[i
]>>15<<15;now
^=sum
;v
.pb(__builtin_popcount(now
));mx
=max(mx
,__builtin_popcount(now
));}for(auto &x
:v
) x
=mx
-x
;if(mp
.count(v
)) {ans
=mp
[v
]+sum
;}return;}dfs2(u
+1,sum
+(1<<u
));dfs2(u
+1,sum
);
}int main()
{
scanf("%d",&n
);for(int i
=1;i
<=n
;i
++) scanf("%d",&a
[i
]);dfs1(0,0); dfs2(15,0);cout
<<ans
<<endl
;return 0;
}
總結
以上是生活随笔為你收集整理的Educational Codeforces Round 76 (Rated for Div. 2) F. Make Them Similar 折半搜索的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。