zoukankan      html  css  js  c++  java
  • sss

    <更新提示>

    <第一次更新>


    <正文>

    开关问题(POJ 1830)

    Description

    有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。你的目标是经过若干次开关操作后使得最后N个开关达到一个特定的状态。对于任意一个开关,最多只能进行一次开关操作。

    你的任务是,计算有多少种可以达到指定状态的方法。(不计开关操作的顺序)

    Input Format

    输入第一行有一个数K,表示以下有K组测试数据。 每组测试数据的格式如下: 第一行 一个数N(0 < N < 29) 第二行 N个0或者1的数,表示开始时N个开关状态。 第三行 N个0或者1的数,表示操作结束后N个开关的状态。 接下来 每行两个数I J,表示如果操作第 I 个开关,第J个开关的状态也会变化。每组数据以 0 0 结束。

    Output Format

    如果有可行方法,输出总数,否则输出“Oh,it's impossible~!!” 不包括引号

    Sample Input

    2  
    3  
    0 0 0  
    1 1 1  
    1 2  
    1 3  
    2 1  
    2 3  
    3 1  
    3 2  
    0 0  
    3  
    0 0 0  
    1 0 1  
    1 2  
    2 1  
    0 0  
    

    Sample Output

    4  
    Oh,it's impossible~!!  
    

    解析

    (x_i)代表是否操作了第(i)个开关,按了为(1),不按为(0)(f_{ij})代表开关(i)和开关(j)的联系情况,按下(j)会影响(i)(f_{ij}=1),反之(f_{ij}=0),对于任意的(i),令(f_{ii}=1)

    如果将第(i)个开关最后是否变化记为(p_i)的话,就可以得到异或方程组:

    [egin{cases} f_{11}x_{1} xor f_{12}x_{2} xor ... xor f_{1n}x_n=p_1 \ f_{21}x_{1} xor f_{22}x_{2} xor ... xor f_{2n}x_n=p_2 \ ... \ f_{n1}x_{1} xor f_{n2}x_{2} xor ... xor f_{nn}x_n=p_n end{cases} ]

    同样地,这个方程组也是可以高斯消元的,只需将加减操作改为异或即可。

    对于本题,求的是方案数,那么我们分高斯消元的三种情况处理即可。当方程组恰好有解时,方案数为(1),当方程组无解时,方案数为(0),当方程组无穷解时,记录下自由元的个数(p),由于每个(x)可以取(1)(0),所以方案数为(2^{p})

    由于本题增广矩阵中所有元素非(1)(0),所以可以状态压缩一下,方便运算。

    (Code:)

      #include <bits/stdc++.h>
    using namespace std;
    const int N=30;
    int n,f[N],ans,t;
    inline void input(void)
    {
        scanf("%d",&n);
        for (int i=1;i<=n;i++)
            scanf("%d",&f[i]);
        int x,y;
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            f[i] ^= x;
        }
        while ( scanf("%d%d",&x,&y) && x && y )
            f[y] |= 1 << x;
    }
    inline void init(void)
    {
        for (int i=1;i<=n;i++)
            f[i] |= 1 << i;
    }
    inline void Gauss(void)
    {
        ans = 1;
        for (int i=1;i<=n;i++)
        {
            for (int j=i+1;j<=n;j++)
                if ( f[j] > f[i] )
                    swap(f[j],f[i]);
            if (!f[i]){ans = 1 << (n-i+1);break;}
            if (f[i]==1){ans = 0;break;}
            for (int j=n;j>=1;j--)
            {
                if (f[i] >> j & 1)
                {
                    for (int k=1;k<=n;k++)
                        if ( i ^ k && ( f[k] >> j & 1 ) )
                            f[k] ^= f[i];
                    break;
                }
            }
        }
    }
    int main(void)
    {
        freopen("switch.in","r",stdin);
        freopen("switch.out","w",stdout);
        scanf("%d",&t);
        while (t--)
        {
            input();
            init();
            Gauss();
            if ( !ans )printf("Oh,it's impossible~!!
    ");
            else printf("%d
    ",ans);
        }
        return 0;
    }
    

    <后记>

  • 相关阅读:
    Power BI 根据用户权限动态生成导航跳转目标
    Power BI Tooltips 增强功能
    Power BI refresh error “could not load file or assembly…provided impersonation level is invalid”
    SQL 错误代码 18456
    如何使用SQL Server Integration Services从多个Excel文件读取数据
    通过表格编辑器将现有表引入Power BI数据流
    Power BI 中动态增长的柱状图
    ambari2.7.3离线安装hdp3.1.0时,ambari-hdp-1.repo中baseurl无值
    ambari 安装 cannot download file mysql-connector-java from http://8080/resource/mysql-connector-java.jar
    洛谷P4180 [BJWC2010]严格次小生成树
  • 原文地址:https://www.cnblogs.com/Parsnip/p/10716893.html
Copyright © 2011-2022 走看看