2012-A3-0003

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

题意是求:给出K个N位的数,某个数能否被其中若干个数xor表示,如果不能修改1位或者2位或者3位表示出来,修改的越少越好,修改后的数越小越好,否则输出NA.

xor空间显然是线性的,于是只要关于这K个数求出任意一组基,任意一组基的张成可以表示K个数的线性张成。

此题中可以规定基的每个分量的优先级,比如高位优先,就可以比较方便的实现求基和张成的操作。

{{{
#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned num;
num k,m,n;
num read(){
    static char buf[32];
    num ret =0;
    for(char* p=gets(buf);*p;++p)
        ret= ret<<1|(*p=='1');
    return ret;
}
void write(num x){
    for(num i=n;i--;)
        putchar(x>>i&1 ?'1':'0');
    putchar('\n');
}
struct{
    num base[32],cnt;
#define hi __builtin_clz
    bool test(num x){
        for(num i=0;i<cnt && x;++i)
            if(hi(x)==hi(base[i]) )x^=base[i];
        return x==0;
    }
    void span(num x){
        for(num i=0;i<cnt && x;++i)
            if(hi(x)==hi(base[i]))x^=base[i];
        if(x){
            base[cnt++]=x;
            for(num i=cnt-1;i;--i)
                if(base[i]>base[i-1])swap(base[i],base[i-1]);
                else break;
        }
    }
}xorbase;
int main(){
    for(;3==scanf("%u%u%u ",&n,&k,&m);){
        for(xorbase.cnt=0;k--;)
            xorbase.span(read());
        for(num x,a;m--;){
            x=read();a=~0;
            bool ok = false;
            if(xorbase.test(x)){
                write(x);continue;
            }
            for(num i=0;i<n;++i)
            if(xorbase.test(x^1<<i)){
                ok =1;
                a= min(a,x^1<<i);
            }
            if(ok){write(a);continue;}
            for(num i=0;i<n;++i)
                for(num j=i+1;j<n;++j)
                    if(xorbase.test(x^1<<i^1<<j)){
                    ok =1;
                    a= min(a,x^1<<i^1<<j);
                }
            if(ok){write(a);continue;}
            for(num i=0;i<n;++i)
                for(num j=i+1;j<n;++j)
                    for(num k=j+1;k<n;++k)
                    if(xorbase.test(x^1<<i^1<<j^1<<k)){
                        ok =1;
                        a= min(a,x^1<<i^1<<j^1<<k);
                    }
            if(ok)write(a);else puts("NA");
        }
    }
    return 0;
}
}}}

题意是求:给出K个N位的数,某个数能否被其中若干个数xor表示,如果不能修改1位或者2位或者3位表示出来,修改的越少越好,修改后的数越小越好,否则输出NA.

xor空间显然是线性的,于是只要关于这K个数求出任意一组基,任意一组基的张成可以表示K个数的线性张成。

此题中可以规定基的每个分量的优先级,比如高位优先,就可以比较方便的实现求基和张成的操作。

#include<cstdio>
#include<algorithm>
using namespace std;
typedef unsigned num;
num k,m,n;
num read(){
    static char buf[32];
    num ret =0;
    for(char* p=gets(buf);*p;++p)
        ret= ret<<1|(*p=='1');
    return ret;
}
void write(num x){
    for(num i=n;i--;)
        putchar(x>>i&1 ?'1':'0');
    putchar('\n');
}
struct{
    num base[32],cnt;
#define hi __builtin_clz
    bool test(num x){
        for(num i=0;i<cnt && x;++i)
            if(hi(x)==hi(base[i]) )x^=base[i];
        return x==0;
    }
    void span(num x){
        for(num i=0;i<cnt && x;++i)
            if(hi(x)==hi(base[i]))x^=base[i];
        if(x){
            base[cnt++]=x;
            for(num i=cnt-1;i;--i)
                if(base[i]>base[i-1])swap(base[i],base[i-1]);
                else break;
        }
    }
}xorbase;
int main(){
    for(;3==scanf("%u%u%u ",&n,&k,&m);){
        for(xorbase.cnt=0;k--;)
            xorbase.span(read());
        for(num x,a;m--;){
            x=read();a=~0;
            bool ok = false;
            if(xorbase.test(x)){
                write(x);continue;
            }
            for(num i=0;i<n;++i)
            if(xorbase.test(x^1<<i)){
                ok =1;
                a= min(a,x^1<<i);
            }
            if(ok){write(a);continue;}
            for(num i=0;i<n;++i)
                for(num j=i+1;j<n;++j)
                    if(xorbase.test(x^1<<i^1<<j)){
                    ok =1;
                    a= min(a,x^1<<i^1<<j);
                }
            if(ok){write(a);continue;}
            for(num i=0;i<n;++i)
                for(num j=i+1;j<n;++j)
                    for(num k=j+1;k<n;++k)
                    if(xorbase.test(x^1<<i^1<<j^1<<k)){
                        ok =1;
                        a= min(a,x^1<<i^1<<j^1<<k);
                    }
            if(ok)write(a);else puts("NA");
        }
    }
    return 0;
}