codeforces 251D

11 篇文章 0 订阅
1 篇文章 0 订阅

题目描述

给你 n105 个数,让你分成两个集合,设第一个集合的数的异或值为 x1 ,第二个集合的数的异或值为 x2 ,空集的异或和定义为 0 ,让你求一个使得x1+x2的值最大,并且满足最大条件下 x1 的值最小的方案。

解题思路

首先你会发现,如果二进制中第 i 位一共有奇数个1,那么这一位一定会给答案增加 2i 的贡献,因为奇数个 1 分成两堆,一定有一堆为奇数个,一堆为偶数个。

如果二进制中第i位有偶数个 1 ,那么我肯定尽量使得两堆都分得奇数个1,那么这一位就会对答案贡献 22i ,而且肯定是尽量满足高位。

这样的话就可以得到 60 个异或方程。

例如:
a1,1x1a2,1x2...an,1xn=f1

ai,j 表示第 i 个数的第j位是否为 1 ,表示异或,若这一位一共有奇数个 1 ,那么f值为0,否则为1.

参考代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<bitset>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 100005
#define maxsq 62
#define ll long long
using namespace std;

bitset<maxn> f[maxsq+5],g[maxsq+5];

int n,tot;

int ans[maxn];

ll sum;

int p[maxsq+5];

int main(){
    scanf("%d",&n);
    fo(i,1,n) {
        ll x;
        scanf("%I64d",&x);
        sum ^= x;
        fo(j,0,maxsq)
            if (x & (1ll << j)) g[j][i]=1;
    }
    fo(bit,0,1) {
        fd(i,maxsq,0)
            if (((sum >> i) & 1)==bit) {
                f[++tot]=g[i];
                if (bit==0) f[tot][n+1]=1;
                else f[tot][n+1]=0;
                fo(j,1,tot-1)
                    if (f[tot][p[j]]) f[tot] ^= f[j];
                p[tot]=n+2;
                fo(j,1,n)
                    if (f[tot][j]) {
                        p[tot]=j;
                        break;
                    }
                if (p[tot]>n) {
                    tot--;
                    continue;
                }
                fo(j,1,tot-1)
                    if (f[j][p[tot]]) f[j] ^= f[tot];
            }
    }
    fo(i,1,tot) ans[p[i]]=f[i][n+1];
    fo(i,1,n) printf("%d ",2-ans[i]);
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值