洛谷 P2447 [SDOI2010]外星千足虫

题目链接

裸的高斯消元求异或方程组

但是怎么考虑最少需要几条信息呢?

考虑我们寻找某列为1的行的过程,实际上就是在找最早出现的那条信息

所以只要找到后break就可以了


#include<bits/stdc++.h>
using namespace std;

const int N = 1050;
const int M = 2050;

int n,m;

bitset<N> g[M];
char s[N];

int ans[N];

int main(){
	scanf("%d%d",&n,&m);
	
	for(int i = 1; i <= m; ++ i) {
	    scanf("%s",s);
	    for(int j = 0; j < n; ++ j) 
	    if(s[j] == '1') g[i][j + 1] = 1;
	    int x; scanf("%d",&x);
	    if(x) g[i][n + 1] = 1;
	}
	
	int now, col;
	int maxx = -1;
	
	for(now = 1, col = 1; now <= m && col <= n; ++ now, ++ col){
	    /*for(int i = 1; i <= m; ++ i)
	    {
	        printf("%d:\n",i);
	        for(int j = 1; j <= n + 1; ++ j) 
	        printf("%d ",g[i][j] ? 1 : 0);
	        puts("");
	    }*/
	    int ps = -1;
	    for(int i = now; i <= m; ++ i){
	        if(g[i][col]) { ps = i; break; }
	    }
	    
	    if(ps == -1) { printf("Cannot Determine\n"); return 0; }
	    maxx = max(maxx, ps);
	    
	    if(ps != now) swap(g[now],g[ps]);
	    
	    for(int i = now + 1; i <= m; ++ i){
	        if(g[i][col]){
	            g[i] ^= g[now];
	        }
	    }
	}
	printf("%d\n",maxx);
	for(int i = n; i >= 1; -- i){
	    ans[i] = g[i][n + 1];
	    for(int j = n; j > i; -- j) ans[i] ^= (ans[j] & g[i][j]);
	}
	for(int i = 1; i <= n; ++ i) 
    puts(ans[i] ? "?y7M#" : "Earth");
	
    return 0;
}

posted @ 2020-07-24 16:24  zhuzihan  阅读(150)  评论(0编辑  收藏  举报