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