您的位置:首页 > 其它

hdu 3364 开关灯问题水题。(高斯消元解模线性方程组)

2018-01-28 22:06 239 查看
本人代码模板主要来自“英雄哪里出来”。该博客对于高斯消元的入门讲解十分详尽。

此题可以不用异或方程组来解,可以用模线性方程组来解。

题意:给定灯的数目和开关数目,以及开关控制哪些灯(一个开关可以控制多盏灯)。

        之后,给出灯的状态(0:关,1:开) 。问:达到最后灯的状态方法有几种。

大致思路:以对每个开关(S)的操作为变量x(可以理解为取值只有0和1,偶数次操作等于没有操作),

                以某盏灯(L)被开关控制的情况为系数,被那个开关控制则对应变量的系数为1,不被那个开关控制

                则对应变量系数为0.最后建立模2的线性方程组。

                (S1*X1+S2*X2+...+Sn*Xn)%2=L1

                (S1'*X1+S2'*X2+...+Sn'*Xn)%2=L2

                              .

                              .

                              .

本题wa点:矩阵在运算过程中是会变的,可以事先开一个二维数组来存储原始矩阵

AC代码如下:

/*模板主要出自英雄从哪里来*/

#include<iostream>

#include<cstdio>

#include<cstring>

#include<string>

#include<algorithm>

using namespace std;

#define IO ios::sync_with_stdio(false)

#define MAXN 105

typedef long long GG;

#define LL GG

#define ll GG

class GaussMatrix{

public:

    int r,c;

    LL d[MAXN][MAXN];

    LL x[MAXN];  //某个解集

    LL xcnt;     //解集个数

    LL abs(LL v){

        return v<0?-v:v;

    }

    void swap_row(int ra,int rb){//行交换 

        for(int i=0;i<=c;i++){

            LL tmp=d[ra][i];

            d[ra][i]=d[rb][i];

            d[rb][i]=tmp;

        }

    }

    void swap_col(int ca,int cb){

        for(int i=0;i<r;i++){

            LL tmp=d[i][ca];

            d[i][ca]=d[i][cb];

            d[i][cb]=tmp;

        }

    }

    LL gauss(LL mod){

        int i,j,k;

        int col,maxrow;

        for(i=0,col=0;i<r&&col<c;i++) {

            maxrow=i;

            for(j=i+1;j<r;j++){

                if(abs(d[j][col])>abs(d[maxrow][col])){

                    maxrow=j;

                }

            }

            if(maxrow!=i){

                swap_row(i,maxrow);

            }

            if(d[i][col]==0){

                col++;

                i--;

                continue;

            }

            for(j=i+1;j<r;j++){

                if(d[j][col]){

                    LL lastcoff = d[i][col];

                    LL nowcoff = d[j][col];

                    for(k=col;k<=c;k++){

                        d[j][k]=(d[j][k]*lastcoff-d[i][k]*nowcoff)%mod;

                        if(d[j][k]<0) d[j][k] +=mod; 

                    }

                }

            }

            col++;

        }

    for(j=i;j<r;j++) {

        if(d[j][c]){

            return -1;

        }

    }

    int free_num=c-i;

    for(i=0;i<r&&i<c;i++){

        if(!d[i][i]){

            for(j=i+1;j<c;j++){

                if(d[i][j]) break;

            }

            if(j<c){

                swap_col(i,j);

            }

        }

    }

    xcnt=(((LL)1)<<(LL)free_num);

    //getAns(mod);

    return xcnt;

    }

   

};

ll t,L,S,n,temp,ans,gg;

LL d[MAXN][MAXN];

int main()

{

    //ll xx=1125899906842624;

    //cout<<xx<<endl;

    GaussMatrix a;

    IO;

    cin>>t;

    gg=t;

    while(t--)

    {

        cout<<"Case "<<gg-t<<':'<<endl;

        cin>>L>>S;

        memset(a.d,0,sizeof(a.d));

        memset(d,0,sizeof(d));

        a.r=L,a.c=S;

        for(int i=1;i<=S;i++){

            cin>>n;

            for(int j=1;j<=n;j++){

                cin>>temp;

                d[temp-1][i-1]=a.d[temp-1][i-1]=1;

            }

        }

        cin>>n;

       // gg=n;

        while(n--){

            for(int i=0;i<L;i++){

                cin>>temp;

                a.d[i][S]=temp;

            }

            ans=a.gauss(2);

            if(ans==-1) cout<<0<<endl;

            else

                cout<<ans<<endl;

            //if(n)

            for(int i=0;i<L;i++){//wa点

                for(int j=0;j<S;j++){

                    a.d[i][j]=d[i][j];

                }

            }

        }

    }

    return 0;

}

              
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM 高斯消元