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;
}
原文地址:https://www.cnblogs.com/gryzy/p/15110539.html