前言
sto 退火大师_slb orz
sto 正解大师_KHIN orz
只有我啥也不会,哈哈。
有趣的是,两种方法我都想到了一部分,然后都寄掉了。
这有趣个锤子。
解析
Sol1
考虑枚举最终的popcount,然后限制就变成了一个类似于高斯消元的形式。
但是和正常的高消不同的是,本题的所有变量都有值域限制(01变量)。
然后就尬住了(悲
考虑meet in the middle。
暴力枚举前15个01变量的取值,得到一个n元组,用map或哈希表存下。
再枚举后15个,得到另一个n元组,然后就可以求出与之唯一匹配的另一个n元组,在map中查询即可。
复杂度 O(30∗215∗n)O(30*2^{15}*n)O(30∗215∗n)。
Sol2
由于需要考虑的变量只有30个,考虑模拟退火。
然后由于我的估价函数用的是极差,挂的很彻底(
(一部分也是因为我当时觉得退火在玩泥巴,没有认真思考)
极差的话很可能操作来操作去最后结果都是一样的,就很难受。
用方差就好了。
代码
//luogu
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned ll
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("ok\n")const int N=105;
const bool Flag=1;inline ll read() {ll x(0),f(1);char c=getchar();while(!isdigit(c)) {if(c=='-')f=-1;c=getchar();}while(isdigit(c)) {x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
bool mem1;int n,k;
int a[N][33],mi[N],x[N];
const int bas=71;
map<ull,int>mp;
int res1[N],res2[N];
void dfs1(int k,int s){if(k>15){ull h(0);for(int i=1;i<=n;i++) h=h*(bas)+res1[i]+31;//for(int i=1;i<=n;i++) printf("%d ",res1[i]);//printf("%d\n",s);mp[h]=s;return;}dfs1(k+1,s);for(int i=1;i<=n;i++){res1[i]+=a[i][k];}dfs1(k+1,s|(1<<(k-1)));for(int i=1;i<=n;i++){res1[i]-=a[i][k];}return;
}
void dfs2(int k,int s){if(k>30){ ull h(0);for(int i=1;i<=n;i++) h=h*(bas)+res2[i]+31; //for(int i=1;i<=n;i++) printf("%d ",res2[i]);//printf("%d\n",s);if(mp.count(h)){printf("%d\n",s+mp[h]);for(int i=1;i<=n;i++){assert(__builtin_popcount(x[i]^(s+mp[h]))==__builtin_popcount(x[1]^(s+mp[h])));}exit(0);}return;}dfs2(k+1,s);for(int i=1;i<=n;i++){res2[i]-=a[i][k];}dfs2(k+1,s|(1<<(k-1)));for(int i=1;i<=n;i++){res2[i]+=a[i][k];}return;
}
void check(int k){//printf("k=%d\n",k);memset(a,0,sizeof(a));for(int i=1;i<=n;i++){a[i][31]=k;//printf(" i=%d x=%d\n",i,x[i]);for(int j=1;j<=30;j++){if(x[i]&mi[j]){a[i][31]--;a[i][j]=-1;}else a[i][j]=1;}}//for(int i=1;i<=n;i++){// for(int j=1;j<=31;j++) printf("%d ",a[i][j]);// puts("");//}for(int i=1;i<=n;i++){res1[i]=0;res2[i]=a[i][31];}mp.clear(); dfs1(1,0);dfs2(16,0);return;
}bool mem2;
signed main() {#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a.out","w",stdout);#endifn=read();for(int i=1;i<=n;i++){x[i]=read();if(__builtin_parity(x[i])!=__builtin_parity(x[1])){//printf("%d\n",i);puts("-1");return 0;}}mi[1]=1;for(int i=2;i<=30;i++) mi[i]=mi[i-1]<<1;for(int i=1;i<=30;i++) check(i);puts("-1");return 0;
}