传送门
文章目录
题意:
思路:
一个显然的思路就是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 折半搜索的全部内容,希望文章能够帮你解决所遇到的问题。
如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。