Codeforces #251D: Two Sets 题解

标签: Codeforces 高斯消元 贪心
3人阅读 评论(0) 收藏 举报
分类:

考虑贪心
按照位从高到低考虑,假设当前正在考虑第i位
如果第i位是1的数有奇数个,那么无论怎么分配,总会有一个人拿到奇数个,另一个人拿到偶数个,所以X1和X2的第i位一定有一个是1,另一个是0,无论怎么分配都是不会影响X1+X2的
如果第i位是1的数有偶数个,那么要么两个人都拿偶数个,这时X1和X2的第i位都是0,要么两个人都拿奇数个,这时X1和X2的第i位都是1,后者的X1+X2肯定是大于前者的,由二进制的性质可得,只要能满足后者,就一定应该满足
考虑怎样描述这样的一个限制;我们设第i位是1的数的下标是a1,a2ak,对每一个位置记录一个Xi,Xi=1表示这个数分给第一个人,Xi=0表示分给第二个人,这样我们的限制条件可以写成这样:xa1xa2...xak=1
这样的一些异或方程组可以用高斯消元搞,每次添一个方程,检查是否还有解
注意添加一个新方程后,不要把整个方程组解一遍,只要对新方程消元就好了
用bitset压位,总复杂度O(n64)

*感觉学完线性基以后,理解高斯消元更加深刻。感觉这两个东西其实很像
*判断方程无解的方法是:消元之后,如果有一个方程,左边全是0,右边不为0,则无解

#include <cstdio>
#include <iostream>
#include <cstring>
#include <string>
#include <cstdlib>
#include <utility>
#include <cctype>
#include <algorithm>
#include <bitset>
#include <set>
#include <map>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <cmath>
#define LL long long
#define LB long double
#define x first
#define y second
#define Pair pair<int,int>
#define pb push_back
#define pf push_front
#define mp make_pair
#define LOWBIT(x) x & (-x)
using namespace std;

const int MOD=1e9+7;
const LL LINF=2e16;
const int INF=1e9;
const int magic=348;
const double eps=1e-10;
const double pi=3.14159265;

inline int getint()
{
    char ch;int res;bool f;
    while (!isdigit(ch=getchar()) && ch!='-') {}
    if (ch=='-') f=false,res=0; else f=true,res=ch-'0';
    while (isdigit(ch=getchar())) res=res*10+ch-'0';
    return f?res:-res;
}

inline LL getLL()
{
    char ch;LL res;bool f;
    while (!isdigit(ch=getchar()) && ch!='-') {}
    if (ch=='-') f=false,res=0; else f=true,res=ch-'0';
    while (isdigit(ch=getchar())) res=res*10+ch-'0';
    return f?res:-res;
}

typedef bitset<100048> bs;

struct equation
{
    bs b;int res;
    inline void init() {b=0;res=0;}
}cur;
map<int,equation> b;
bool exist[100048];

int n;
LL a[100048];
int maxbit;
int ans[148];
int sol[100048];

inline bool check()
{
    int bit,i;
    for (i=1;i<=n;i++)
        if (cur.b[i])
            if (exist[i]) cur.b^=b[i].b,cur.res^=b[i].res; else {b[i]=cur;exist[i]=true;return true;}
    if (cur.res) return false; else return true;
}

inline void find_solution()
{
    int i,j;
    for (i=n;i>=1;i--)
    {
        if (!exist[i]) {sol[i]=0;continue;}
        for (j=i+1;j<=n;j++)
            if (b[i].b[j]) b[i].res^=sol[j];
        sol[i]=b[i].res;
    }
}       

int main ()
{
    int i,bit;n=getint();
    for (i=1;i<=n;i++) a[i]=getLL();
    for (maxbit=63;maxbit;maxbit--)
    {
        bool f=false;
        for (i=1;i<=n;i++)
            if (a[i]&(1ll<<(maxbit-1))) {f=true;break;}
        if (f) break;
    }
    for (bit=maxbit;bit;bit--)
    {
        cur.init();
        for (i=1;i<=n;i++)
            if (a[i]&(1ll<<(bit-1))) cur.b[i]=1,cur.res++;
        if (cur.res%2==1) {ans[bit]=1;continue;}
        cur.res=1;
        if (check()) ans[bit]=2; else ans[bit]=0;
    }
    for (bit=maxbit;bit;bit--)
        if (ans[bit]==1)
        {
            cur.init();
            for (i=1;i<=n;i++)
                if (a[i]&(1ll<<(bit-1))) cur.b[i]=1;
            cur.res=0;
            check();
        }
    find_solution();
    for (i=1;i<=n;i++) printf("%d ",2-sol[i]);
    return 0;
}
查看评论

Codeforces 251D Two Sets

贪心+高斯消元
  • sdfzyhx
  • sdfzyhx
  • 2017-05-16 09:13:15
  • 179

【CF251D】Two Sets

【CF251D】Two Sets:Philips非常喜欢数字。最近pwecar送给他了一个由n个非负整数组成的集合。Philips非常喜欢和Bing玩。他立即决定把他n个数字中的一部分送给Bing。为...
  • Cold_Chair
  • Cold_Chair
  • 2018-03-26 12:12:12
  • 54

Codeforces 469D Two Sets 题解

Codeforces 469D题解
  • m0_37729344
  • m0_37729344
  • 2017-06-22 16:06:58
  • 171

codeforces 468B Two Sets 并查集变形

题目链接: 题目大意:给你N个数,再给
  • u011632342
  • u011632342
  • 2014-09-23 17:31:41
  • 514

CodeForces 468B Two Sets 二分匹配

题目链接:点击打开链接 题意:给定n个数,常数a, b 把n个数放到集合A和集合B 使得: 对于某个数x,若x在A集合则 a-x也必须在A集合(若a-x不存在于n个数中,则x不能放在A集合) ...
  • qq574857122
  • qq574857122
  • 2014-12-21 13:04:38
  • 1557

Codeforces 469D Two Sets【思维+并查集】

D. Two Sets time limit per test 1 second memory limit per test 256 megabytes input stand...
  • mengxiang000000
  • mengxiang000000
  • 2017-05-01 19:39:54
  • 358

Codeforces 468B Two Sets(二分图匹配)

题目链接:Codeforces 468B Two Sets 题目大意:给出n个数,要求将n个数分配到两个集合中,集合0中的元素x,要求A-x也再0中,同理1集合。 解题思路:类似二分图匹配的方法。...
  • u011328934
  • u011328934
  • 2014-09-25 10:31:11
  • 1258

Codeforces 468B Two Sets 并查集

题目大意:给出n个数,要求将n个数分配到两个集合中,集合0中的元素x,要求A-x也再0中,同理1集合。 写了几个版本,一直WA在第8组数据...最后参考下ans,写了并查集过了 学到:1、...
  • u011026968
  • u011026968
  • 2014-09-28 15:55:50
  • 1021

codeforces 468B Two Sets 2-sat

题意:给n个不同的数,希望把
  • u011645923
  • u011645923
  • 2014-09-22 00:42:29
  • 801

codeforces 468B Two Sets 并查集

题目链接:cf 468B B. Two Sets time limit per test 1 second memory limit per test 256 meg...
  • u010535824
  • u010535824
  • 2014-09-23 13:31:13
  • 382
    个人资料
    持之以恒
    等级:
    访问量: 9553
    积分: 1459
    排名: 3万+
    最新评论