zoukankan      html  css  js  c++  java
  • BZOJ1923: [Sdoi2010]外星千足虫

    BZOJ1923: [Sdoi2010]外星千足虫

    Description

    Input

    第一行是两个正整数 N, M。 接下来 M行,按顺序给出 Charles 这M次使用“点足机”的统计结果。每行 包含一个“01”串和一个数字,用一个空格隔开。“01”串按位依次表示每只虫 子是否被放入机器:如果第 i 个字符是“0”则代表编号为 i 的虫子未被放入,“1” 则代表已被放入。后面跟的数字是统计的昆虫足数 mod 2 的结果。 由于 NASA的实验机器精确无误,保证前后数据不会自相矛盾。即给定数据 一定有解。

    Output

    在给定数据存在唯一解时有 N+1行,第一行输出一个不 超过M的正整数K,表明在第K 次统计结束后就可以确定唯一解;接下来 N 行 依次回答每只千足虫的身份,若是奇数条足则输出“?y7M#”(火星文),偶数 条足输出“Earth”。如果输入数据存在多解,输出“Cannot Determine”。 所有输出均不含引号,输出时请注意大小写。

    Sample Input

    3 5
    011 1
    110 1
    101 0
    111 1
    010 1

    Sample Output

    4
    Earth
    ?y7M#
    Earth

    HINT

    对于 20%的数据,满足 N=M≤20; 
    对于 40%的数据,满足 N=M≤500; 
    对于 70%的数据,满足 N≤500,M≤1,000; 
    对于 100%的数据,满足 N≤1,000,M≤2,000。 


    题解Here!
    咕了好多天才写完这题。。。
    这其实就是个类似高斯消元的解法。
    首先这题显然要高斯消元解异或方程组。
    但是这题$N$有点大,可以用$bitset$优化。
    最开始想的是二分找这个满足要求的最小的$K$ ,无奈复杂度$O(N^2log_2N)$过不去。。。
    考虑高斯消元的过程,假设当前在消第$i$列,第$j$行,那么一定是从第$j$行向下找一个最小的$p$,满足$a[p][i]=1$。
    这里的最小的就已经满足题目要求了,不必要在二分了。
    也就是说,每次$swap$时取一个$max$即可。
    其他就跟高斯消元一模一样了。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<bitset>
    #define MAXN 1010
    using namespace std;
    int n,m;
    bitset<MAXN> a[MAXN<<1];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    void work(){
    	int ans=0;
    	for(int i=1;i<=n;i++){
    		int k=i;
    		while(k<=m&&!a[k][i])k++;
    		if(k==m+1){
    			printf("Cannot Determine
    ");
    			return;
    		}
    		ans=max(ans,k);
    		if(k!=i)swap(a[k],a[i]);
    		for(int j=1;j<=m;j++){
    			if(i==j||!a[j][i])continue;
    			a[j]^=a[i];
    		}
    	}
    	printf("%d
    ",ans);
    	for(int i=1;i<=n;i++){
    		if(a[i][n+1])printf("?y7M#
    ");
    		else printf("Earth
    ");
    	}
    }
    void init(){
    	char ch[MAXN];
    	n=read();m=read();
    	for(int i=1;i<=m;i++){
    		scanf("%s",ch+1);
    		for(int j=1;j<=n;j++)a[i][j]=ch[j]-'0';
    		a[i][n+1]=read();
    	}
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    
  • 相关阅读:
    flock对文件锁定读写操作的问题 简单
    hdu 2899 Strange Fuction(二分)
    hdu 2199 Can you solve this equation? (二分)
    poj 3080 Blue Jeans (KMP)
    poj 2823 Sliding Window (单调队列)
    poj 2001 Shortest Prefixes (trie)
    poj 2503 Babelfish (trie)
    poj 1936 All in All
    hdu 3507 Print Article (DP, Monotone Queue)
    fzu 1894 志愿者选拔 (单调队列)
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9534348.html
Copyright © 2011-2022 走看看