标签:scan log can 开关 个数 long pre 它的 htm
https://www.cnblogs.com/downrainsun/p/11228690.html
完成套路:往自己这里搬。
性质:
设数集T的值域范围为[1,2^n−1]。
T的线性基是T的一个子集A={a1,a2,a3,...,an}。
A中元素互相xor所形成的异或集合,等价于原数集T的元素互相xor形成的异或集合。
可以理解为将原数集进行了压缩。
性质
1.设线性基的异或集合中不存在0。
2.线性基的异或集合中每个元素的异或方案唯一,其实这个跟性质1是等价的。
3.线性基二进制最高位互不相同。
4.如果线性基是满的,它的异或集合为[1,2^n−1]。
5.线性基中元素互相异或,异或集合不变。
接下来是题目:
一,洛谷彩灯
给你m个开关,每个开关表示可以控制哪些灯的状态,且状态取反,亮则暗,暗则亮,求多少种不重复的灯亮状态
题解:首先可以知道的是那些开关实际上就是异或操作,那么考虑到不重复,那就想到线性基
线性基性质A中元素互相xor所形成的异或集合,等价于原数集T的元素互相xor形成的异或集合。,同时不出现重复,那接下来就好办了,成功解决不重复问题,就算线性基有多少个数存在,然后2的个数次方就完事
#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);
}
标签:scan log can 开关 个数 long pre 它的 htm
原文地址:https://www.cnblogs.com/hgangang/p/11783101.html