SGU 275 - To xor or not to xor 按位贪心 + XOR性质

给n个数,任选若干个,使得异或值最大


引理:

【假设集合A,其中我们将ai替换成ai xor a[j] i<>j,那么得到的新集合,这个集合中元素能xor出的值于集合A相同】

实际本题用到的是:

也就是说要ans 去异或上 A[1..n]的任意个数时,对应了一个值域A

如果你先让ans^=A[1],然后去用A[1]异或上所有A[2..n],此时用ans异或上 A[2..N]的任意个,对应的值域B = 上面的值域A


算法:

按位贪心

从高位到低位枚举二进制位D


1.找出第L位为1的数ai,如果找到则转2,否则转4

2.若ans的第L位为0,ans^=ai,若为1则不异或ai

3.使所有第L位为1的数aj^=ai。(不管2中的ans是否有异或ai)

4.枚举下一个二进制位。


void solve(ll init,int N,ll A[])
{
     ll rt=0;
    for (int i=62;i>=0;i--)
    { 
        for (int j=1;j<=N;j++)
        {
            if((A[j]>>i)&1)
            {  
                if(!((rt>>i)&1)) rt^=A[j];
                for (int k=1;k<=N;k++)
                if((k!=j)&&((A[k]>>i)&1))
                    A[k]^=A[j];
                A[j]=0;
            } 
        }
    }
    cout<<rt<<endl;
}


几个问题:

对于步骤2,如果选到一个第X位为1的数,如果此时ans的x位=0,则ans^=A[i],再用A[i]去异或上所有x位为1的数,最后ans的值域与异或A[i]之前的一样的(根据引理)


如果此时ans的x位为1,是否可以直接跳过

不可以,显然算法的每一步都应该保证把所有数的X位置零,否则后面的异或操作会修改的ans的值

其次,那么按照步骤2,ans没异或A【i】,步骤3却依旧要用A【i】异或上所有 X位为1的数,是否就改变了值域了?

如果此时是ans异或上任意个A[i]的话,值域确实改变了!!

但是显然,如果当前ans的X位已经是1,那么我们只能在这些 X位为1的A【i】(共k个)中选取偶数个,这对应了一个值域C

于是我们把 这些X位为1的A【i】任选一个,去异或上别的所有X位为1的A【i】,再去掉A[i],此时我们剩下k-1个 X位为1的A[i]

不管我们怎么选这k-1个数,都能得到 原来的k个A[i]值异或后的结果。

也就是 在 ans的x位为1时,我们只能从X位为1的A【i】中任选偶数个A[i],在这个条件下,做完步骤3之后,ans就可以从新的k-1个A[i]中选任意个,并且对应的值域D与原来的值域C是相等的!


复杂度:60*n

由于每次只消一位,显然只需要消去60次

参考学习blog:http://blog.csdn.net/greatwjj/article/details/20942281

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值