标签: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