zoukankan      html  css  js  c++  java
  • 【高斯消元解xor方程】BZOJ1923-[Sdoi2010]外星千足虫

    【题目大意】

    有n个数或为奇数或为偶数,现在进行m次操作,每次取出部分求和,告诉你这几次操作选取的数和它们和的奇偶性。如果通过这m次操作能得到所有数的奇偶性,则输出进行到第n次时即可求出答案;否则输出无法确定。

    【思路】

    高斯消元解xor方程组,求最少需要的方程个数或判断无法确定。

    无法确定即存在自由元,在每次操作中找1的时候判断一下就好了;最小方程个数,就是记录下每次找到的最小的1的位置,最后输出最大值即可。

    【错误】

    忘记把ans改为-1了(见程序注释)

    【备注】

    P.S.我看别人在高斯消元的过程中都是当前行和所有行xor一遍,而不是从下一行开始;然后结果就不需要回代了只需直接输出第n+1列即可??不适合呢明白????

    在莫涛和proverbs那里找到答案了:

    考虑系数矩阵,每行是一个方程,每列是一个未知数在各个方程中的系数(将第i行的方程的所有系数状压到一个数 a[i]里,可以用bitset)。
    我们分析一下消元之后各个方程系数的状况:
    由于我们每次选择最大的一个 a[i],并且找到它最高位上的1,把其它所有方程(包含当前行以上的方程)这一位的系数全部消去,也就是说对于每个方程,它的系数 a[i]最高位上的1所在的那一列,仅有这一个1,其余的都是0。再进一步,如果方程个数n足够多的话,那么消元之后系数矩阵的每一行仅有一个1,并且这个1所在的那一列也仅有这一个1

     1 /*回代的做法*/
     2 /**************************************************************
     3     Problem: 1923
     4     Language: C++
     5     Result: Accepted
     6     Time:244 ms
     7     Memory:1556 kb
     8 ****************************************************************/
     9  
    10 #include<iostream>
    11 #include<cstdio>
    12 #include<cstring>
    13 #include<algorithm>
    14 #include<bitset>
    15 using namespace std;
    16 const int MAXN=1000+50;
    17 const int MAXM=2000+50;
    18 bitset<MAXN> map[MAXM];
    19 int n,m;
    20 int times=-1;
    21  
    22 void Gauss()
    23 {
    24     for (int i=1;i<=n;i++)
    25     {
    26         int t=i;
    27         for (;t<=m && !map[t][i];t++);
    28         if (t>m) 
    29         {
    30             times=-1;//这里times要清成-1 
    31             return;
    32         }
    33         if (t!=i) swap(map[i],map[t]);
    34         times=max(times,t);
    35         for (int j=i+1;j<=m;j++) 
    36             if (map[j][i])
    37                 map[j]^=map[i];
    38     }
    39      
    40 }
    41  
    42 void init()
    43 {
    44     scanf("%d%d",&n,&m);
    45     for (int i=0;i<m;i++)
    46     {
    47         char str[MAXN];
    48         int mapans;
    49         scanf("%s%d",str,&mapans);
    50         map[i+1][n+1]=mapans;
    51         for (int j=0;j<n;j++) map[i+1][j+1]=str[j]-'0';
    52     }
    53 }
    54  
    55 void print_ans()
    56 {
    57     if (times==-1) cout<<"Cannot Determine"<<endl;
    58         else
    59         {
    60             printf("%d
    ",times);
    61             for (int i=n;i>=1;i--)
    62                 for (int k=i+1;k<=n;k++)
    63                     if (map[i][k]) 
    64                     {
    65                         int tmp=map[i][n+1]^map[k][n+1];
    66                         map[i][n+1]=tmp;
    67                     }
    68             for (int i=1;i<=n;i++)
    69                 puts((map[i][n+1])?"?y7M#":"Earth");
    70         }
    71 }
    72  
    73 int main()
    74 {
    75     init();
    76     Gauss();
    77     print_ans();
    78 }

    额变慢了……仿佛被欺骗了感情……谁来告诉我一下??!!

    /*不回代的做法*/
    /**************************************************************
        Problem: 1923
        Language: C++
        Result: Accepted
        Time:284 ms
        Memory:1556 kb
    ****************************************************************/
     
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<bitset>
    using namespace std;
    const int MAXN=1000+50;
    const int MAXM=2000+50;
    bitset<MAXN> map[MAXM];
    int n,m;
    int times=-1;
     
    void Gauss()
    {
        for (int i=1;i<=n;i++)
        {
            int t=i;
            for (;t<=m && !map[t][i];t++);
            if (t>m) 
            {
                times=-1;//这里times要清成-1 
                return;
            }
            if (t!=i) swap(map[i],map[t]);
            times=max(times,t);
            for (int j=1;j<=m;j++) 
                if (i!=j && map[j][i])
                    map[j]^=map[i];
        }
         
    }
     
    void init()
    {
        scanf("%d%d",&n,&m);
        for (int i=0;i<m;i++)
        {
            char str[MAXN];
            int mapans;
            scanf("%s%d",str,&mapans);
            map[i+1][n+1]=mapans;
            for (int j=0;j<n;j++) map[i+1][j+1]=str[j]-'0';
        }
    }
     
    void print_ans()
    {
        if (times==-1) cout<<"Cannot Determine"<<endl;
            else
            {
                printf("%d
    ",times);
                for (int i=1;i<=n;i++)
                    puts((map[i][n+1])?"?y7M#":"Earth");
            }
    }
     
    int main()
    {
        init();
        Gauss();
        print_ans();
    }
  • 相关阅读:
    Android学习总结——实现Home键功能
    Android学习总结——SQLite
    Android学习总结——文件储存
    Android学习总结——SharedPreferences
    Android学习总结——Content Provider
    Android学习总结——Service组件
    IDEA 创建和使用tomcat
    IDEA 图标介绍。 缓存和索引介绍、清理方法和Debug使用
    IDEA 常用快捷键
    IntelliJ IDEA常用设置(一)
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5670008.html
Copyright © 2011-2022 走看看