codeforces 251D

題目描述

給你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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章