题目大意: 有一个长度为 n n n 的序列,一开始全都是 0 0 0,有 m m m 种操作,每个操作可以将序列里的一些位置翻转( 0 0 0 变 1 1 1, 1 1 1 变 0 0 0),问通过这 m m m 种操作,可以将序列变成多少种样子。
题解
要想到,既然每一种操作形如一个 01 01 01 串,那么每进行一次该操作,就相当于将序列异或上这个操作。因为这些 01 01 01 串的长度都只有 n n n,假如转化成 10 10 10 进制的话, l o n g l o n g long~long long long是可以存的下的,那问题就变成了:有 m m m 个数,问能异或出多少个不同的数。
显然,这个就是线性基的模板题了。
构造出这 m m m 个数的线性基,设线性基中包含 k k k 个元素,那么 2 k 2^k 2k 便是答案。
代码如下:
#include <cstdio>
#include <cstring>
#define ll long long
int n,m;
ll d[60];
char s[60];
void add(ll x)
{
for(int i=50;i>=0;i--)
{
if(x&(1ll<<i))
{
if(d[i]==0)
{
d[i]=x;
return;
}
else x^=d[i];
}
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%s",s+1);
ll x=0;
for(int j=1;j<=n;j++)
if(s[n-j+1]=='O')x^=(1ll<<(j-1));
add(x);
}
int ans=0;
for(int i=0;i<=50;i++)
if(d[i]!=0)ans++;
printf("%lld",(1ll<<ans)%2008);
}