zoukankan      html  css  js  c++  java
  • 洛谷3857 [TJOI2008]彩灯

    线性基入门:

    给你一个数列N个数字,构造一个线性基出来。对于原数列任意一个数字,都可通过选取线性基中若干数字XOR运算得到。

    两个公式:

    1:如果A^B^C=0,则A^B=C,如果一个数字C没有加入到线性基中,说明已存在A,B,且A^B=C

    2:如果A^B=C,则A^C=B.

    构造程序如下:

    #include<bits/stdc++.h>
    using namespace std;
    int N,M,cnt,ans;
    long long P[128];
    char s[128];
    void insert(long long x)
    {
        for(int i=62;i>=0;i--)
            if((x>>i)&1)
    		{
                if(!P[i])
    			{
    				P[i]=x;
    				break;
    			}
                else 
    			     x^=P[i];
            }
    }
    int main()
    {
        scanf("%d",&N);
        for(int i=1;i<=N;i++)
    	{   
    		int aa;
    		cin>>aa;
            insert(aa);
        }
        for(int i=0;i<=62;i++)
    	if(P[i])
    	cout<<P[i]<<endl;
        return 0;
    }
    

     运行过程:

    当加入9(1001)的时候,直接加入
    当加入8(1000)的时候,其最高位那个1,所在的位置已有9加入了,
    所以8^9=1,加入之0001
    当加入7(0111)的时候,直接加入。
    当加入6(0110)的时候,直接加入,其最高位那个1,所在的位置已有7加入了,
    所以6^7=0001,然后1又已在线性基中了,xor后得到0,不加入。
    当加入5(0101)的时候,其最高位那个1,所在的位置已有7加入了
    所以5^7=2,加入之0010
    当加入4后,4^5^1=0,不加入
    当加入3后,3^2^1=0,不加入

    当加入2后,不加入

    当加入1后,不加入
    ..................
    最终形成的线性基为9,1,7,2.总个数是最小的,且这些数转成4位2进制后
    其最高位如果为1的,将是各个数字中是唯一的。

    注意构造出来的线性基并不是唯一的。

     对于上面这个数列,线性基为(1,2,4,8)也是可以的。

    已知一组彩灯是由一排N个独立的灯泡构成的,并且有M个开关控制它们。从数学的角度看,这一排彩灯的任何一个彩灯只有亮与不亮两个状态,所以共有2N个样式。由于技术上的问题,Peter设计的每个开关控制的彩灯没有什么规律,当一个开关被按下的时候,它会把所有它控制的彩灯改变状态(即亮变成不亮,不亮变成亮)。假如告诉你他设计的每个开关所控制的彩灯范围,你能否帮他计算出这些彩灯有多少种样式可以展示给他的女朋友?

    注: 开始时所有彩灯都是不亮的状态。

    输入输出格式

    输入格式:

    每组测试数据第一行为两个整数N和M,用空格隔开。紧接着是有M行,每行都是一个长度为N的字符串,表示一个开关控制彩灯的范围(N盏灯),如果第i个字母是大写字母’O’,则表示这个开关控制第i盏灯,如果第i个字母是大写字母’X’,则表示这个开关不控制此灯。

    输出格式:

    输出这些开关和彩灯可以变换出来的样式数目。
    由于这个值可能会很大,请求出它对于整数2008的余数。

    输入输出样例

    输入样例#1:
    2 3
    OO
    XO
    OX
    输出样例#1:
    4
    说明

    可见样例中第一个开关控制了所有的彩灯,而后两个开关分别控制了第一个和第二个彩灯,这样我们可以只用后两个开关控制彩灯,可以变换出来所有的22个状态。

     本题可以翻译成给出M个N位二进制数 , 取若干个异或,求有多少种结果。

    本质就是求出线性基的个数x,结果即为2^x

    线性基就是把原有的集合用一个新的集合替代之,新的集合里面数相互异或可以得出原有集合的数相互异或的答案。

    搞出线性基的性质 : a 和 b 的所有xor 结果 等同于 a和 a xor b的所有结果。

    #include<bits/stdc++.h>
    using namespace std;
    int N,M,cnt,ans;
    long long P[128];
    char s[128];
    void insert(long long x)
    {
        for(int i=62;i>=0;i--)
            if((x>>i)&1){
                if(!P[i]){P[i]=x;break;}
                else x^=P[i];
            }
    }
    int main()
    {
        scanf("%d%d",&N,&M);
        for(int i=1;i<=M;i++){
            scanf("%s",s);
            long long a=0;
            for(int j=0;j<N;j++)
                if(s[j]=='O')a^=(1ll<<j);
            insert(a);
        }
        for(int i=0;i<=62;i++)if(P[i])ans++;
        printf("%lld",(1ll<<ans)%2008);
        return 0;
    }
    

      

  • 相关阅读:
    Linux常用命令-centos
    USACO 2006 Open, Problem. The Country Fair 动态规划
    USACO 2007 March Contest, Silver Problem 1. Cow Traffic
    USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法
    USACO 2015 February Contest, Silver Problem 3. Superbull Prim最小生成树算法
    LG-P2804 神秘数字/LG-P1196 火柴排队 归并排序, 逆序对
    数据结构 并查集
    浴谷国庆集训 对拍
    1999 NOIP 回文数
    2010 NOIP 普及组 第3题 导弹拦截
  • 原文地址:https://www.cnblogs.com/cutemush/p/12761817.html
Copyright © 2011-2022 走看看