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