一类开关问题,经典问题。而线性基实质上也是在做高斯消元。
给出
n
≤
50
n\leq50
n≤50个彩灯,但每个灯最多只有开关两种状态。然后有
m
m
m组开关控制器给出控制的是哪几盏灯。求问彩灯有多少种不同的状态。
开关控制状态的叠加可以认为是两个
01
01
01向量的异或。
m
m
m组开关可以看成
m
m
m行
n
n
n列的方程组。然后对其消元得到方程组的秩
R
R
R,答案就是
2
R
2^{R}
2R。
原因:任意一个异或结果(也就是开关的状态)都可以由线性基表示出来,而线性基任意两个不同子集的异或和都不同,否则就存在集合异或和为
0
0
0,不满足线性基的性质了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=55;
char s[N];
ll a[N],b[N];
int main() {
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {
scanf("%s",s);
for(int j=0;j<n;j++) {
a[i]+=(s[j]=='O'?1:0)*(1LL<<(n-j-1));
}
}
for(int i=1;i<=m;i++) {
ll x=a[i];
for(int j=n-1;j>=0;j--) {
if(x&(1LL<<j)) {
if(!b[j]) {
b[j]=x;
break;
}
else x^=b[j];
}
}
}
int cnt=0;
for(int i=0;i<n;i++) {
if(b[i]) ++cnt;
}
printf("%lld\n",(1LL<<cnt)%2008);
return 0;
}