zoj 3636 Decode

来源:互联网 发布:数据库原理视频教程 编辑:程序博客网 时间:2024/05/20 22:29

题目链接: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|1using 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;}


0 0