team2012-F3-sol-0003

从 Trac 迁移的文章

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

原文章内容如下:

{{{
题意:给定k个长度为n的0-1向量作为码字,对于每个给出的询问,回答是否能用这些码字异或表示,且错误位少于3位
解法:这k个码进行任意的组合,形成一个线性空间,先求出这个空间的一组基,然后对于每个询问的码枚举错误位,再看是否能用基表示出来。
}}}
{{{
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

int n, k, m, code[20005], base[40];

int tr(char* s)
{
    int tmp = 0;
    for(int j = 0; j < n; j++)
        if(s[j] == '1')
            tmp += (1<<(n-1-j));
    return tmp;
}

void print(int x)
{
    if(x==-1)
        printf("NA\n");
    else
    {
        for(int i=n-1;i>=0;i--)
            if(x&(1<<i))
                printf("1");
            else
                printf("0");
        printf("\n");
    }
}

void gao_ji()
{
    int bs,
        bs_ind[40] = {0},
        bs_col[40] = {0};
    bool sel[20005] = {0};

    for(int i=n-1;i>=0;i--)
    {
        int find = 0;
        for(int j=1;j<=k;j++)
            if(!sel[j] && (code[j] & (1<<i)))
            {
                find = 1;
                sel[j] = 1;
                bs = code[j];
                bs_ind[++bs_ind[0]] = j;
                bs_col[++bs_col[0]] = i;
                break;
            }
        if(find)
            for(int j=1;j<=k;j++)
                if((code[j]&(1<<i)) && j!=bs_ind[bs_ind[0]])
                    code[j] ^= bs;
    }
    memset(base, -1, sizeof(base));
    for(int i=1;i<=bs_ind[0];i++)
        base[bs_col[i]] = code[bs_ind[i]];
}

bool test(int x)
{
    for(int i=n-1;i>=0;i--)
        if(x&(1<<i))
        {
            if(base[i] == -1)
                return 0;
            x ^= base[i];
        }
    return 1;
}

int decode(int x)
{
    if(test(x))
        return x;
    int ans = 0x7FFFFFFF,
        err = 4;

    for(int i=0;i<n;i++)
    {
        int t = x^(1<<i);
        if(test(t))
            if(err>1 || (err==1 && t<ans))
            {
                ans = t;
                err = 1;
            }
        if(err >= 2)
            for(int j=i+1;j<n;j++)
            {
                t = x^(1<<i)^(1<<j);
                if(test(t))
                    if(err>2 || (err==2 && t<ans))
                    {
                        ans = t;
                        err = 2;
                    }
                if(err >= 3)
                    for(int k=j+1;k<n;k++)
                    {
                        t = x^(1<<i)^(1<<j)^(1<<k);
                        if(test(t))
                            if(err>3 || (err==3 && t<ans))
                            {
                                ans = t;
                                err = 3;
                            }
                    }
            }
    }

    if(err<=3)
        return ans;
    else
        return -1;
}

int main()
{
    while(~scanf("%d %d %d", &n, &k, &m))
    {
        memset(code, 0, sizeof(code));
        for(int i = 1; i <= k; i++)
        {
            char str[40];
            scanf("%s", str);

            code[++code[0]] = tr(str);
        }

        memset(base, 0, sizeof(base));
        gao_ji();

        for(int i = 1; i <= m; i++)
        {
            char str[40];
            scanf("%s", str);

            int rec = tr(str),
                ans = decode(rec);
            print(ans);
        }
    }

    return 0;
}
}}}
题意:给定k个长度为n的0-1向量作为码字,对于每个给出的询问,回答是否能用这些码字异或表示,且错误位少于3位
解法:这k个码进行任意的组合,形成一个线性空间,先求出这个空间的一组基,然后对于每个询问的码枚举错误位,再看是否能用基表示出来。
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n, k, m, code[20005], base[40];
int tr(char* s)
{
    int tmp = 0;
    for(int j = 0; j < n; j++)
        if(s[j] == '1')
            tmp += (1<<(n-1-j));
    return tmp;
}
void print(int x)
{
    if(x==-1)
        printf("NA\n");
    else
    {
        for(int i=n-1;i>=0;i--)
            if(x&(1<<i))
                printf("1");
            else
                printf("0");
        printf("\n");
    }
}
void gao_ji()
{
    int bs,
        bs_ind[40] = {0},
        bs_col[40] = {0};
    bool sel[20005] = {0};
    for(int i=n-1;i>=0;i--)
    {
        int find = 0;
        for(int j=1;j<=k;j++)
            if(!sel[j] && (code[j] & (1<<i)))
            {
                find = 1;
                sel[j] = 1;
                bs = code[j];
                bs_ind[++bs_ind[0]] = j;
                bs_col[++bs_col[0]] = i;
                break;
            }
        if(find)
            for(int j=1;j<=k;j++)
                if((code[j]&(1<<i)) && j!=bs_ind[bs_ind[0]])
                    code[j] ^= bs;
    }
    memset(base, -1, sizeof(base));
    for(int i=1;i<=bs_ind[0];i++)
        base[bs_col[i]] = code[bs_ind[i]];
}
bool test(int x)
{
    for(int i=n-1;i>=0;i--)
        if(x&(1<<i))
        {
            if(base[i] == -1)
                return 0;
            x ^= base[i];
        }
    return 1;
}
int decode(int x)
{
    if(test(x))
        return x;
    int ans = 0x7FFFFFFF,
        err = 4;
    for(int i=0;i<n;i++)
    {
        int t = x^(1<<i);
        if(test(t))
            if(err>1 || (err==1 && t<ans))
            {
                ans = t;
                err = 1;
            }
        if(err >= 2)
            for(int j=i+1;j<n;j++)
            {
                t = x^(1<<i)^(1<<j);
                if(test(t))
                    if(err>2 || (err==2 && t<ans))
                    {
                        ans = t;
                        err = 2;
                    }
                if(err >= 3)
                    for(int k=j+1;k<n;k++)
                    {
                        t = x^(1<<i)^(1<<j)^(1<<k);
                        if(test(t))
                            if(err>3 || (err==3 && t<ans))
                            {
                                ans = t;
                                err = 3;
                            }
                    }
            }
    }
    if(err<=3)
        return ans;
    else
        return -1;
}
int main()
{
    while(~scanf("%d %d %d", &n, &k, &m))
    {
        memset(code, 0, sizeof(code));
        for(int i = 1; i <= k; i++)
        {
            char str[40];
            scanf("%s", str);
            code[++code[0]] = tr(str);
        }
        memset(base, 0, sizeof(base));
        gao_ji();
        for(int i = 1; i <= m; i++)
        {
            char str[40];
            scanf("%s", str);
            int rec = tr(str),
                ans = decode(rec);
            print(ans);
        }
    }
    return 0;
}