zoukankan      html  css  js  c++  java
  • 【洛谷2447】[SDOI2010] 外星千足虫(异或高斯消元)

    点此看题面

    • (n)(01)变量,给定(m)个方程,每个方程给出若干个元素的异或和。
    • 问至少使用前几个方程即可求出所有元素值。
    • (nle10^3,mle2 imes10^3)

    线性基+高斯消元

    显然,能解出所有元素值的充要条件就是有(n)个方程,满足任意一个都无法由其他若干个推得。

    发现这个条件有点眼熟,如果我们把每个方程看作一个(n)位的二进制数,就变成要满足任意一个数都无法由其他若干个异或得到。

    这不就是一个线性基嘛!

    所以我们只要维护一个线性基,当元素个数达到(n)的时候就说明此时可以解出所有元素了。

    由于这时候满足第(i)个方程只有第(isim n)个元素可能有值,因此我们只要执行高斯消元的最后一步操作,从后往前枚举每一个元自之前的方程中消去即可。

    具体实现可以用(bitset)优化复杂度。

    代码:(O(frac{n^3}{32}))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 1000
    using namespace std;
    int n,m,v[N+5];bitset<N+5> s,a[N+5];char st[N+5];
    I void Gauss()//轻量版高斯消元
    {
    	RI i,j;for(i=n;i;--i) for(j=i-1;j;--j) a[j].test(i)&&(a[j]^=a[i],0);//枚举每一个元素从之前的方程中消除
    	for(i=1;i<=n;++i) puts(a[i].test(0)?"?y7M#":"Earth");//输出答案
    }
    int main()
    {
    	RI i,j,x,t=0;for(scanf("%d%d",&n,&m),i=1;i<=m;++i)
    	{
    		for(scanf("%s%d",st+1,&x),s.reset(),x&&(s.set(0),0),j=1;j<=n;++j) st[j]&1&&(s.set(j),0);//转化成二进制数
    		for(j=1;j<=n;++j) if(s.test(j)) {if(a[j].any()) s^=a[j];else {a[j]=s,++t;break;}}//维护线性基
    		if(t==n) return printf("%d
    ",i),Gauss(),0;//元素个数达到n说明能解出所有元素了
    	}return puts("Cannot Determine"),0;//始终无法
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    如何书写bat文件?(转)
    Bogon
    recursive
    ssh
    verbose
    mii-tool
    ExtJs 中的ext.date
    一个打包机~~~
    图标库--宝藏
    几种常用的控件(下拉框 可选框 起止日期 在HTML页面直接读取当前时间)
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu2447.html
Copyright © 2011-2022 走看看