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; } }