• [SDOI2010]外星千足虫 题解 高斯消元+bitset简介


    高斯消元 + bitset 简介:

    高斯消元其实就是以加减消元为核心求唯一解。这道题还是比较裸的,可以快速判断出来。我们将每一只虫子看作一个未知数,这样根据它给出的 m 组方程我们可以高斯消元得出每一只虫子的归属地。如果你还不清楚高斯消元的原理可以移步此处

    如果你只是以为这是一道板子题自信提交,那么恭喜你,你将会获得TLE的好成绩。为什么呢?我们知道高斯消元是 $ n^3 $ 复杂度的,而本题数据范围 $ n leq 1000 $ ,$ m leq 2000 $ ,明显会卡出TLE。

    于是乎,bitset登场了,先介绍一下:

    bitset是一种专门用来储存二进制的数组,使用前要先调用函数库。

    他的每一个元素只占 1 bit空间,你可以将它当作bool类型的高精度。

    他的优点很多,你可将他整体使用,也可单个访问,例如:

    bitset<4> a (string("1001"));
    bitset<4> b (string("0011"));
    //注:bitset后面那对尖括号里的数表示a数组的大小
    a+=b;
    //此时a数组为1100
    a[3]=1;
    a[1]=0;
    //此时a数组为1001
    
    

    你不访问它单个的值是,bitset的运算就像一个普通的整数一样,可以进行与(&)、或(|)、异或(^)、左移(<<)、右移(>>)等操作。同时你还可以对这个数里的任意一位赋值修改。

    这样我们就可以将高斯消元降为二维,将每一个方程用一个bitset维护,在用异或运算进行消元即可。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<iomanip>
    #include<algorithm>
    #include<bitset>//调用bitset函数库
    
    #define ll long long
    #define db double
    #define inf 0x7fffffff
    
    using namespace std;
    
    bitset<1005> s[2001];
    int n,m,ans,now=1;
    
    inline int qr(){//快读
    	char ch;
    	while((ch=getchar())<'0'||ch>'9');
    	int res=ch^48;
    	while((ch=getchar())>='0'&&ch<='9')
    		res=(res<<1)+(res<<3)+(ch^48);
    	return res;
    }
    
    inline int rd(){
    	char ch;
    	while((ch=getchar())<'0'||ch>'9');
    	return ch^48;//每次只读一个
    }
    
    int main(){
    	//freopen(".in","r",stdin);
    	//freopen(".out","w",stdout);
    	n=qr()+1,m=qr();
    	for(int i=1;i<=m;++i)//读入
    		for(int j=1;j<=n;++j)
    			s[i][j]=rd();
    	for(int i=1;i<n;now=++i){
    		while(!s[now][i]&&now<=m)++now;
    		ans=max(ans,now);//更新 k 值
    		if(now==m+1){
    			printf("Cannot Determine
    ");
    			return 0;
    		} //方程不构成唯一解
    		if(now!=i)swap(s[i],s[now]);
    		for(int j=1;j<=m;j++){
    			if(i==j)continue; //不消自己
    			if(!s[j][i])continue;//不是1就不用消
    			s[j]^=s[i];//用异或消去系数 1
    		}//消去其他方程的系数
    	}
    	printf("%d
    ",ans);
    	for(int i=1;i<n;++i)
    		if(s[i][n])printf("?y7M#
    ");
    		else printf("Earth
    ");
    	return 0;
    }
    

    bitset除了可以整体运算外还有很多功能:

    foo.size()  	返回大小(位数)
    foo.count() 	返回1的个数
    foo.any()   	返回是否有1
    foo.none()  	返回是否没有1
    foo.set()   	全都变成1
    foo.set(p)  	将第p + 1位变成1
    foo.set(p, x)   将第p + 1位变成x
    foo.reset() 	全都变成0
    foo.reset(p)    将第p + 1位变成0
    foo.flip() 	 全都取反
    foo.flip(p) 	将第p + 1位取反
    foo.to_ulong()  返回它转换为unsigned long的结果,如果超出范围则报错
    foo.to_ullong() 返回它转换为unsigned long long的结果,如果超出范围则报错
    foo.to_string() 返回它转换为string的结果
    
    ✐☎博主撰文不易,转载还请注明出处;若对本文有疑,请私信或在下方讨论中提出。O(∩_∩)O谢谢!☏

    ☃〔尽管小伙伴们肯定有千百种方式针对,但博主还是极其非常十分不要脸的把反对键吃掉辣!〕☃

    ✿『$At$ $last$:非常一(hu)本(shuo)正(ba)经(dao)的:博主很笨,请不要欺负他』✿✍

  • 相关阅读:
    (9)在结果中筛选
    (8)为列表结果分页
    (7)为结果排序
    (6)找回忘记的密码
    (3)验证用户的输入
    (5)发送欢迎邮件
    (4)实现多语言
    (2)通过脚手架自动生成controller和view ----代码先行/数据库先行
    (1)用密码保护限制对view的访问
    (转)scanf()总结
  • 原文地址:https://www.cnblogs.com/812-xiao-wen/p/9872897.html
Copyright © 2020-2023  润新知