4
2
2015
0

CF上的一些题目

[153D]给出n个数,你需要将n个数分到两个集合,不妨记第一个集合的异或和为X1,第二个为X2。要求X1+X2最大,保证这个前提下X1最大。输出方案。

题解:想起来其实不难。从低到高考虑,如果sum(X1^X2)的第i位为1,那么X1和X2的这一位不用,但加起来肯定是1.而如果sum 的这一位是0,那么两者就可能都是0或者都是1.我们就加入到当前的方程组中判断是否能都是1。能的话就保留这个更改,否则去除这个方程。做了一遍之后我们在考虑X1最大这个条件。如果sum第i位0为1,那么考虑X1这一位能不能是1.具体做法和上面一样了。但是写起来感觉会很蛋疼。。。于是膜拜了status里的代码。

bitset<maxn>f[70],g[70];
int n,m,c[maxn],p[maxn];
ll sum;
int main()
{
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
    n=read();
    for1(i,n)
    {
    	ll x=read();sum^=x;
    	for0(j,62)if(x>>j&1)g[j][i]=1;
    }
    for0(w,1)//第一遍把sum位为0的确定能不能X1和X2都为1,第二遍把sum位为1的确定能不能让X1为1.Orz!!! 
     for3(i,62,0)if((sum>>i&1)==w)
     {
     	f[++m]=g[i];f[m][n+1]=1;p[m]=inf;
     	for1(j,m-1)if(f[m][p[j]])f[m]^=f[j];//用上面的结果来消这个方程 
     	for1(j,n)if(f[m][j]){p[m]=j;break;}//该方程第一位为1的位置 
     	if(p[m]>n)m--;//无用方程或者不可能成立的方程 
		else for1(j,m-1)if(f[j][p[m]])f[j]^=f[m]; //把上面的这一位都消掉 
     }
    for1(i,m)c[p[i]]=f[i][n+1];//确定答案,这时候每个方程一定都被消的只剩一个主元了 
    for1(i,n)printf("%d%c",c[i]+1,i==n?'\n':' ');	
    return 0;
}

 

Category: codeforces | Tags: | Read Count: 637

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

| Theme: Aeros 2.0 by TheBuckmaker.com