problem1 link
其实就是找到一个数字$t$,使得$x$的二进制为1 的位上$t$也都为1。然后$t$删掉所有那些$x$为1的二进制位就是$k$。
problem2 link
设所有合法的边的个数为$m(m \leq C_{10}^{2}=45)$。状态$mask$记录每个点的度数。$f[i][j]$表示处理到第$i$条边,目前每个点度数的状态为$j$ 的最小距离。不需要记录选的边的个数是因为可以从$j$推算出来。
problem3 link
将$n$平分为前一半后一半,两边分别暴力枚举出每种选择的差值。
统计答案的时候只需要枚举一侧(假设差值为$x$,某一个集合里的已选的个数为$t$),然后在另一侧寻找选到该集合个数为$\frac{n}{2}-t$且差值最接近$-x$,然后更新答案即可。
code for problem1
import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class BitwiseEquations { public long kthPlusOrSolution(int x, int k) {
long result=0;
long t=x;
int cur=0;
int m=30;
while(0==(k&(1<<m))) {
--m;
}
for(int i=0;i<=m;++i) {
while((t&(1l<<cur))!=0) {
++cur;
}
if((k&(1<<i))!=0) {
result|=1l<<cur;
}
++cur;
}
return result;
}
}
code for problem2
import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class TwinTowns { public int[] optimalTwinTowns(int[] x,int[] y, int maxPartners, int minDistance) {
final int n=x.length; List<Integer> pairs=new ArrayList<>(); for(int i=0;i<n;++i) {
for(int j=i+1;j<n;++j) {
if(dist(i,j,x,y)>=minDistance) {
pairs.add(i*100+j);
}
}
}
final int M=1<<(n<<1);
int[][] f=new int[2][M];
int pre=0,cur=1;
for(int i=1;i<M;++i) {
f[0][i]=-1;
}
for(int i=1;i<=pairs.size();++i) {
final int p1=pairs.get(i-1)/100;
final int p2=pairs.get(i-1)%100;
for(int j=0;j<M;++j) {
f[cur][j]=f[pre][j];
}
for(int j=0;j<M;++j) {
if(f[pre][j]!=-1) {
int nj=add(j,p1,p2,maxPartners);
if(nj!=-1&&(f[cur][nj]==-1||f[cur][nj]>f[pre][j]+dist(p1,p2,x,y))) {
f[cur][nj]=f[pre][j]+dist(p1,p2,x,y);
}
}
}
pre^=1;
cur^=1;
}
int maxEdges=-1;
int minSumDist=0;
for(int i=0;i<M;++i) {
if(f[pre][i]!=-1) {
final int e=getEdges(i);
if(e>maxEdges) {
maxEdges=e;
minSumDist=f[pre][i];
}
else if(e==maxEdges&&f[pre][i]<minSumDist) {
minSumDist=f[pre][i];
}
}
}
return new int[]{maxEdges,minSumDist};
} int getEdges(int mask) {
int sum=0;
while(mask!=0) {
sum+=mask&3;
mask>>=2;
}
return sum>>1;
} int add(int mask,int t1,int t2,int maxPartners) {
for(int i=0;i<2;++i) {
final int pos=i==0?t1:t2;
final int x=getBit(mask,pos)+1;
if(x>maxPartners) {
return -1;
}
mask=reset(mask,pos,x);
}
return mask;
} int getBit(int mask,int pos) {
return (mask>>(pos<<1))&3;
}
int reset(int mask,int pos,int val) {
mask=mask^(((mask>>(pos<<1))&3)<<(pos<<1));
return mask|(val<<(pos<<1));
} int dist(int i,int j,int[] x,int[] y) {
return Math.abs(x[i]-x[j])+Math.abs(y[i]-y[j]);
}
}
code for problem3
import java.util.*;
import java.math.*;
import static java.lang.Math.*; public class PickingUp { static class pair {
public int mask;
public long delta; public pair() {
mask=0;
delta=0;
}
} static class MyComparator implements Comparator<pair> {
public int compare(pair a,pair b) {
if(a.delta!=b.delta) {
return a.delta<b.delta?-1:1;
}
return a.mask<b.mask?-1:1;
}
} public int[] fairPickingUp(long[] score1, long[] score2) {
final int n=score1.length>>1;
List<List<pair>> list1=new ArrayList<>();
List<List<pair>> list2=new ArrayList<>();
for(int i=0;i<=n;++i) {
list1.add(new ArrayList<>());
list2.add(new ArrayList<>());
}
int[] f=new int[1<<n];
for(int i=1;i<(1<<n);++i) {
f[i]=f[i>>1]+(i&1);
}
for(int i=0;i<(1<<n);++i) {
for(int k=0;k<2;++k) {
final int start=k==0?0:n;
pair p=new pair();
p.mask=i;
for(int j=0;j<n;++j) {
if((i&(1<<(n-1-j)))==0) {
p.delta-=score1[j+start];
}
else {
p.delta+=score2[j+start];
}
}
if(k==0) {
list1.get(f[i]).add(p);
}
else {
list2.get(f[i]).add(p);
}
}
}
MyComparator comparator=new MyComparator();
for(int i=0;i<=n;++i) {
Collections.sort(list1.get(i),comparator);
Collections.sort(list2.get(i),comparator);
}
list1=unique(list1);
long minMask=-1;
long minCost=1l<<61;
for(int i=0;i<=n;++i) {
for(int j=0;j<list2.get(i).size();++j) {
if(j!=0&&list2.get(i).get(j-1).delta==list2.get(i).get(j).delta) {
continue;
}
final int pos=search(list1.get(n-i),-list2.get(i).get(j).delta);
if(pos==-1) {
continue;
}
for(int k=0;k<2;++k) {
if(pos+k<list1.get(n-i).size()) {
pair q=list1.get(n-i).get(pos+k);
final long cost=Math.abs(q.delta+list2.get(i).get(j).delta);
final long mask=((long)q.mask<<n)|list2.get(i).get(j).mask;
if(cost<minCost||cost==minCost&&mask<minMask) {
minCost=cost;
minMask=mask;
}
}
}
}
} int[] result=new int[n<<1];
for(int i=n+n-1;i>=0;--i) {
if((minMask&(1l<<i))==0) {
result[n+n-1-i]=1;
}
else {
result[n+n-1-i]=2;
}
}
return result;
} List<List<pair>> unique(List<List<pair>> lists) {
List<List<pair>> result=new ArrayList<>();
for(int i=0;i<lists.size();++i) {
result.add(new ArrayList<>());
}
for(int i=0;i<lists.size();++i) {
if(lists.get(i).size()==0) {
continue;
}
result.get(i).add(lists.get(i).get(0));
for(int j=1;j<lists.get(i).size();++j) {
if(lists.get(i).get(j-1).delta!=lists.get(i).get(j).delta) {
result.get(i).add(lists.get(i).get(j));
}
}
}
return result;
} int search(List<pair> list,long delta) {
final int s=list.size();
if(s==0) {
return -1;
}
if(list.get(0).delta>=delta) {
return 0;
}
if(list.get(s-1).delta<=delta) {
return s-1;
}
int low=0,high=s-1,result=0;
while(low<=high) {
int mid=(low+high)>>1;
if(list.get(mid).delta<=delta) {
result=Math.max(result,mid);
low=mid+1;
}
else {
high=mid-1;
}
}
return result;
}
}