luogu3857 彩灯
题目描述
Peter 女朋友的生日快到了,他亲自设计了一组彩灯,想给女朋友一个惊喜。已知一组彩灯是由一排 \(N\) 个独立的灯泡构成的,并且有 \(M\)个开关控制它们。从数学的角度看,这一排彩灯的任何一个彩灯只有亮与不亮两个状态,所以共有 \(2^N\)个样式。由于技术上的问题,Peter 设计的每个开关控制的彩灯没有什么规律,当一个开关被按下的时候,它会把所有它控制的彩灯改变状态(即亮变成不亮,不亮变成亮)。假如告诉你他设计的每个开关所控制的彩灯范围,你能否帮他计算出这些彩灯有多少种样式可以展示给他的女朋友?
注: 开始时所有彩灯都是不亮的状态。
输入格式
每组测试数据第一行为两个整数 \(N\) 和 \(M\),用空格隔开。紧接着是有 \(M\) 行,每行都是一个长度为 \(N\) 的字符串,表示一个开关控制彩灯的范围(\(N\) 盏灯),如果第 \(i\) 个字母是大写字母 O,则表示这个开关控制第 \(i\) 盏灯,如果第 \(i\) 个字母是大写字母 X,则表示这个开关不控制此灯。
输出格式
输出这些开关和彩灯可以变换出来的样式数目。由于这个值可能会很大,请求出它对于整数 \(2008\) 的余数。
线性基。
代码不难,关键在思考!
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=55;
ll d[maxn];
int n,m;
char s[maxn];
int cnt;
void insert(ll x)
{
for(int i=50;i>=0;--i)
{
if(x&(1ll<<i))
{
if(d[i])
x^=d[i];
else
{
d[i]=x;
cnt++;
break;
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i)
{
ll x=0;
scanf("%s",s);
for(int i=0;i<n;++i)
if(s[i]=='O')x+=(1ll<<i);
insert(x);
}
cout<<(1ll<<cnt)%2008;
return 0;
}