prow2012-A3-0003
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
题意是求:给出K个N位的数,某个数能否被其中若干个数xor表示,如果不能修改1位或者2位或者3位表示出来,修改的越少越好,修改后的数越小越好,否则输出NA. (zz from zYc)
用类似高斯消元的方法去筛选异或基,对于每个x,用已有基的最高位1消去x的最高位1,如果最后剩余x非0,x加入基。
高效选取最高位1,我用的是二分法。
用dfs枚举C(N,3),依次判断x是否能用基表达。
{{{
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <set>
#include <map>
#include <sstream>
#include <string>
#include <math.h>
using namespace std;
int nlz(unsigned x)
{
int n;
if (x == 0) return(32);
n = 1;
if ((x >> 16) == 0) {n = n +16; x = x <<16;}
if ((x >> 24) == 0) {n = n + 8; x = x << 8;}
if ((x >> 28) == 0) {n = n + 4; x = x << 4;}
if ((x >> 30) == 0) {n = n + 2; x = x << 2;}
n = n - (x >> 31);
return n;
}
int T,base[100];
void add(int x){
int i;
for (i=T-1;x&&i>=0;i--)
if (nlz(x)==nlz(base[i]))
x^=base[i];
if (x){
base[T++] = x;
sort(base,base+T);
}
}
bool test(int x){
int i;
for (i=T-1;x&&i>=0;i--)
if (nlz(x)==nlz(base[i]))
x^=base[i];
return x==0;
}
int N,M,K;
int Min,ans;
void dfs(int now,int sum,int num){
if (now==N&&test(num)){
//printf("%d %d\n",sum,num);
if (sum<Min){
Min = sum,ans = num;
}else if (sum==Min&&ans>num){
ans = num;
}
}
if (sum>Min||now==N) return ;
dfs(now+1,sum,num);
if (sum+1<=3)
dfs(now+1,sum+1,num^(1<<now));
}
int main(){
char str[100];
int i,j;
while(scanf("%d%d%d",&N,&M,&K)!=EOF){
T = 0;
for (i=0;i<M;i++){
scanf("%s",str);
int x = 0;
for (j=0;j<N;j++)
x = (x<<1)+(str[j]=='1');
add(x);
}
Min = 4,ans = 0;
for (i=0;i<K;i++){
int x = 0;
scanf("%s",str);
for (j=0;j<N;j++)
x = (x<<1)+(str[j]=='1');
Min = 4,ans = 0;
dfs(0,0,x);
if (Min==4) puts("NA");
else {
for (j=N-1;j>=0;j--)
printf("%d",((1<<j)&ans)>0);
printf("\n");
}
}
}
}
}}}
题意是求:给出K个N位的数,某个数能否被其中若干个数xor表示,如果不能修改1位或者2位或者3位表示出来,修改的越少越好,修改后的数越小越好,否则输出NA. (zz from zYc)
用类似高斯消元的方法去筛选异或基,对于每个x,用已有基的最高位1消去x的最高位1,如果最后剩余x非0,x加入基。
高效选取最高位1,我用的是二分法。
用dfs枚举C(N,3),依次判断x是否能用基表达。
#include <vector>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <set>
#include <map>
#include <sstream>
#include <string>
#include <math.h>
using namespace std;
int nlz(unsigned x)
{
int n;
if (x == 0) return(32);
n = 1;
if ((x >> 16) == 0) {n = n +16; x = x <<16;}
if ((x >> 24) == 0) {n = n + 8; x = x << 8;}
if ((x >> 28) == 0) {n = n + 4; x = x << 4;}
if ((x >> 30) == 0) {n = n + 2; x = x << 2;}
n = n - (x >> 31);
return n;
}
int T,base[100];
void add(int x){
int i;
for (i=T-1;x&&i>=0;i--)
if (nlz(x)==nlz(base[i]))
x^=base[i];
if (x){
base[T++] = x;
sort(base,base+T);
}
}
bool test(int x){
int i;
for (i=T-1;x&&i>=0;i--)
if (nlz(x)==nlz(base[i]))
x^=base[i];
return x==0;
}
int N,M,K;
int Min,ans;
void dfs(int now,int sum,int num){
if (now==N&&test(num)){
//printf("%d %d\n",sum,num);
if (sum<Min){
Min = sum,ans = num;
}else if (sum==Min&&ans>num){
ans = num;
}
}
if (sum>Min||now==N) return ;
dfs(now+1,sum,num);
if (sum+1<=3)
dfs(now+1,sum+1,num^(1<<now));
}
int main(){
char str[100];
int i,j;
while(scanf("%d%d%d",&N,&M,&K)!=EOF){
T = 0;
for (i=0;i<M;i++){
scanf("%s",str);
int x = 0;
for (j=0;j<N;j++)
x = (x<<1)+(str[j]=='1');
add(x);
}
Min = 4,ans = 0;
for (i=0;i<K;i++){
int x = 0;
scanf("%s",str);
for (j=0;j<N;j++)
x = (x<<1)+(str[j]=='1');
Min = 4,ans = 0;
dfs(0,0,x);
if (Min==4) puts("NA");
else {
for (j=N-1;j>=0;j--)
printf("%d",((1<<j)&ans)>0);
printf("\n");
}
}
}
}