zoj 3636 Decode

题目链接:Decode

题目大意:

有k个长度为n的01串,这些串通过异或组成的集合为S。m个询问,询问一个串是否属于S。修改一个位置后是否属于S,修改2个位置后是否属于S,修改3个位置后是否属于S。如果都不属于S,输出NA。

n≤30,k≤20000,m≤1000

解题思路:

n是比较小的。有点像,提取某一位的分量,然后异或一下组成要询问的字符串。其实就是高斯消元消成上三角矩阵。

然后暴力的N^3枚举出错的位置,验证。


//#pragma comment(linker,"/STACK:102400000,102400000")
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<string>
#define ll long long
#define db double
#define PB push_back
#define lson k<<1
#define rson k<<1|1
using namespace std;

const int N = 20005;

int a[N], n, k;

int str2int(char *s)
{
    int res(0);
    for(int i = 0; i < n; i++)
    {
        res = (res << 1) + s[i] - '0';
    }
    return res;
}

const int M = 35;
int b[M];

void getb()
{
    int base(0);
    for(int i = n - 1; i >= 0; i--)
    {
        b[i] = -1;
        for(int j = 0; j < k; j++)
        {
            if(a[j] & (1 << i) && !(a[j]&base))
            {
                b[i] = a[j];
                int t=a[j];
                for(int p = 0; p < k; p++)
                    if(a[p] & (1 << i)) a[p] ^= t; //?? 
            }
        }
        base |= 1 << i;
    }
//    for(int i=n-1;i>=0;i--) printf("%d ",b[i]);
//    printf("\n");
}

bool check(int num)
{
    if(num == 0) return true;
    int now(0);
    for(int i = n - 1; i >= 0; i--)
    {
        if((num & (1 << i)) ^ (now & (1 << i)))
        {
            if(b[i] == -1) return false;
            now ^= b[i];
        }
    }
    return true;
}

int getans(int num)
{
    int er(10), res(-1);
    for(int i = 0; i < n; i++)
    {
        num ^= (1 << i);
        for(int j = i + 1; j < n; j++)
        {
            num ^= (1 << j);
            for(int p = j + 1; p < n; p++)
            {
                num ^= (1 << p);
                if(check(num))
                {
                    if(3 < er)
                    {
                        er = 3, res = num;
                    }
                    else if(er == 3 && num < res) res = num;
                }
                num ^= 1 << p;
            }
            if(check(num))
            {
                if(2 < er)
                {
                    er = 2, res = num;
                }
                else if(er == 2 && num < res) res = num;
            }
            num ^= (1 << j);
        }
        if(check(num))
        {
            if(1 < er)
            {
                er = 1, res = num;
            }
            else if(er == 1 && num < res) res = num;
        }
        num ^= 1 << i;
    }
//    printf("&&& %d %d\n",num,check(num));
    if(check(num)) return num;
    return (er > 3) ? -1 : res;
}

int main()
{
#ifdef PKWV
    freopen("in.in", "r", stdin);
#endif // PKWV
    int m;
    while(scanf("%d%d%d", &n, &k, &m) + 1)
    {
        for(int i = 0; i < k; i++)
        {
            char str[35];
            scanf("%s", str);
            a[i] = str2int(str);
        }
        getb();
        for(int i = 0; i < m; i++)
        {
            char str[35];
            scanf("%s", str);
            int num = str2int(str);
            int ans = getans(num);
            if(ans == -1) printf("NA");
            else
                for(int j = n - 1; j >= 0; j--) printf("%d", (ans >> j) & 1);
            printf("\n");
        }
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/u014076176/article/details/46940267
ZOJ