《P2447 [SDOI2010]外星千足虫》

非常好的一个题。

首先很显然能构造异或方案组。

但是这里n,m都很大,如果用一般的高斯消元肯定会超时。

这时就可以利用bitset来加速整行的消元操作。

然后就是要考虑怎么取找最少的方案组数量了。

这个我们在消元的时候尽量去找前面的消就可以了。

// Author: levil
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef long double ld;
typedef pair<int,int> pii;
const int N = 1e3 + 5;
const int M = 2e3 + 5;
const LL Mod = 998244353;
#define INF 1e9
#define dbg(ax) cout << "now this num is " << ax << endl;
inline long long ADD(long long x,long long y) {
    if(x + y < 0) return ((x + y) % Mod + Mod) % Mod;
    return (x + y) % Mod;
}
inline long long MUL(long long x,long long y) {
    if(x * y < 0) return ((x * y) % Mod + Mod) % Mod;
    return x * y % Mod;
}
inline long long DEC(long long x,long long y) {
    if(x - y < 0) return (x - y + Mod) % Mod;
    return (x - y) % Mod;
}

bitset<N> a[M];
int Gauss(int n,int m) {//n个变量,m个方程
    int num = -1;
    for(int i = 1;i <= n;++i) {//消去第i个元
        int now = i;
        while(now <= m && !a[now].test(i)) now++;
        if(now > m) return 0;//有多组解
        num = max(num,now);
        if(now != i) swap(a[i],a[now]);
        for(int j = 1;j <= m;++j) {
            if(i != j && a[j].test(i)) a[j] ^= a[i];//可以消元,进行消元
        }
    }
    return num;
}
void solve() {
    int n,m;scanf("%d %d",&n,&m);
    for(int i = 1;i <= m;++i) {
        string s;cin >> s;
        int x;scanf("%d",&x);
        for(int j = 1;j <= n;++j) a[i].set(j,s[j - 1] - '0');
        a[i].set(0,x);
    }
    int pos = Gauss(n,m);
    if(pos <= 0) printf("Cannot Determine\n");
    else {
        printf("%d\n",pos);
        for(int i = 1;i <= n;++i) printf("%s\n",a[i].test(0) ? "?y7M#" : "Earth");
    }


}   
int main() {
    //int ca;scanf("%d",&ca);
    //while(ca--) {
        solve();
    //}
    system("pause");
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/zwjzwj/p/15577471.html