矩阵与高斯消元【矩阵乘法,高斯消元求线性方程组,求行列式】 全网最详,附例题与姊妹篇 一万三千字详解

(详解)矩阵快速幂详解与常见转移矩阵的构造_秦小咩的博客-CSDN博客_矩阵快速幂转移矩阵

目录

矩阵乘法

矩阵快速幂 伪代码模板

例题一

例题2

例题三

例题四

高斯消元

整形高斯消元

浮点型高斯消元

例题

模数型高斯消元

 异或型高斯消元

例题


矩阵乘法

假设有n的地点,从地点i到地点j坐飞机有aij种选择,坐火车有bij种选择。求从地点i先坐飞机再转成火车到j的方案数

cij=\sum_{k=1}^{n} a _{ik} b_{kj}

矩阵乘法

假设 A=(aij),B=(bij)是两个n元矩阵,它们的乘积C=AB也是一个n元矩阵C=(cij),

满足cij=\sum_{k=1}^{n}a_{ik}b_{kj}

矩阵快速幂 伪代码模板

const int N=505;

void matpow()
{
    int ans[N][N];
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        ans[i][j]=(i==j);
    
    while(pow)
    {
        if(pow&1)
            matmul(ans,base,ans);
        matmul(base,base,base);
        
    }
    
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            a[i][j]=ans[i][j];
            
        }
            
    }
}

例题一

Magic Gems

\begin{pmatrix} f(n)\\ \\ \\ \\ \end{pmatrix}            \begin{pmatrix} 1 & 0 & 0 &... &1 \\ & & & & \\ & & & & \\ & & & & \\ & & & & \end{pmatrix} \begin{pmatrix} f(n-1)\\ f(n-2)\\ ...\\ f(n-m)\\ \end{pmatrix}

                        行                            列 

考虑继承

\begin{pmatrix} f(n)\\ f(n-1)\\ ...\\ f(n-m+1)\\ \end{pmatrix}=\begin{pmatrix} 1 & 0& 0&... &1 \\ 1& 0 &0 & ...&0 \\ 0& 1& 0 & ...&0 \\ 0& 0 & 0& ... & 0\\ 0& 0& 0& 1& 0 \end{pmatrix} =\begin{pmatrix} f(n-1)\\ f(n-2)\\ ..\\ f(n-m)\\ \end{pmatrix}

base矩阵是快速幂关键,继承也就有一定技巧性

设F[n]   = base* F[n-1]则

n-m=1时 n-1=m

F[n]=  base ^n-m * F(m)

其中F数组m行   base数组  m行*m列·

# include<cstdio>
# include<algorithm>
# include<iostream>
# include<map>
# include<cstring>
# include<set>
# include<algorithm>
# include<vector>
# include<queue>
# include<cstring>

using namespace  std;
# define mod  1000000007

typedef long long int ll;

ll f[110][110],base[110][110];
ll n,m;

void mul(ll a[110][110],ll b[110][110])
{
    ll c[110][110]= {0};

    for(int i=1; i<=m; i++)
    {
        for(int j=1; j<=m; j++)
        {
            for(int k=1; k<=m; k++)
            {
                c[i][j]=(c[i][j]+a[i][k]*b[k][j]%mod)%mod;
            }
        }
    }
    for(int i=1; i<=m; i++)
    {
        for(int j=1; j<=m; j++)
        {
            a[i][j]=c[i][j]%mod;

        }
    }
}
ll ans[110][110];

int main ()
{


   

    cin>>n>>m;

    base[1][1]=1;

    base[1][m]=1;

    for(int i=2; i<=m; i++)
    {
        base[i][i-1]=1;

    }

    f[1][1]=2;

    for(int i=2; i<=m; i++)
    {
        f[i][1]=1;

    }


    ll pow=n-m;
    
    if(pow<=0)
    {
        if(pow<0)
        cout<<1;
        else
            cout<<2;
        
        return  0;
    
    
    }

    for(int i=1; i<=m; i++)
    {
        ans[i][i]=1;
    }

    while(pow)
    {
        if(pow&1)
        mul(ans,base);

        pow>>=1;

        mul(base,base);

    }

    ll an=0;

    for(int i=1;i<=m;i++)
    {
        an=(an+ans[1][i]*f[i][1]%mod)%mod;

    }

    cout<<an;




    return 0;

}

例题2

方格填色

我们用1代表白色,0代表黑色。左右两格不能同时是白色  &运算之后,一定是0 ,两列不能全是黑也就是两列不能全是0

\begin{pmatrix} f(n,0)\\ f(n,1)\\ ...\\ f(n,st)\\ \end{pmatrix} = \bigl(\begin{smallmatrix} & & & & \\ & & & & \\ & & & & \\ & & & & \\ & & & & \end{smallmatrix}\bigr) *\begin{pmatrix} f(n-1,0)\\ f(n-1,1)\\ ....\\ f(n-1,st{}') \end{pmatrix}        其中base数组的转移规则为,i,j不能同时是0,且ij&运算之后不能是1

另外base数组的pow应该是n-1

# include<cstdio>
# include<algorithm>
# include<iostream>
# include<map>
# include<cstring>
# include<set>
# include<algorithm>
# include<vector>
# include<queue>
# include<cstring>

using namespace  std;
# define mod  1000000007

typedef long long int ll;

ll base[50][50],n,m;

ll f[50][50];
ll ans[50][50];

void cheng(ll a[50][50],ll b[50][50])
{
    ll temp[50][50]={0};

    for(int i=0;i<(1<<m);i++)
    {
        for(int j=0;j<(1<<m);j++)
        {
            for(int k=0;k<(1<<m);k++)
            {
                temp[i][j]=(temp[i][j]+a[i][k]*b[k][j]%mod)%mod;

            }
        }
    }

    for(int i=0;i<(1<<m);i++)
    {
        for(int j=0;j<(1<<m);j++)
        {
            a[i][j]=temp[i][j];

        }
    }
}
int main ()
{

    cin>>m>>n;

    for(int i=0;i<(1<<m);i++)
    {
        for(int j=0;j<(1<<m);j++)
        {
            if(i&j)
                continue;

            if(!i&&!j)
                continue;


            base[i][j]=1;

        }
    }

    ll pow=n-1;


    for(int i=0;i<(1<<m);i++)
    {
        ans[i][i]=1;


        f[i][1]=1;
    }


    while(pow)
    {
        if(pow&1)
        cheng(ans,base);


        pow>>=1;

        cheng(base,base);

    }


    ll an=0;


    for(int i=0;i<(1<<m);i++)
    {
        for(int j=0;j<(1<<m);j++)
        {
            an=(an+ans[i][j]*f[j][1]%mod)%mod;

        }
    }

    cout<<an;



    return 0;

}

例题三

Sasha and Array

首先,菲波那切数列的转移方程

\begin{pmatrix} f(n)\\ f(n-1)\end{pmatrix} = \begin{pmatrix} 1& 1\\ 1& 0 \end{pmatrix} * \begin{pmatrix} f(n-1)\\ f(n-2)\end{pmatrix}

在这里不得不提一个规律,那就是base数组的x次幂所得到的  base[1][1]正好是 f(x-1)

比如0次幂的单位矩阵   base[1][1]=1=f(1)

1次幂    base[1][1]=f(2)

2次幂  base[1][1]=f(3)

而本题的突破点就在这里。

每次进行的区间修改用线段树来实现,那么线段树的实际意义该如何定义?

首先看两项操作  对于[L,R]区间内的a[i]进行加 x,操作  

对于【L,R]区间内的斐波那契数列求和  

第一项操作对于第二项操作的影响在于   每次加x,相当于对f[i]对应的base矩阵进行了幂数+x,也就是乘上一个幂数为x的base矩阵

之后我们线段树的sum数组该如何定义? 我们的lazy标记又该如何定义

首先我们是无法预处理出10^9那么大的斐波那契数列的,也就意味着我们sum数组不能是单纯的数字,应该是矩阵形式。

而sum数组就对应了 该区间base数组之和。 这样的合理性在于 [L,R]之间所有矩阵分别乘x个base矩阵,所得到的base[1][1]之和,与先把矩阵相加,再乘x个base矩阵所得结果相同

在返回答案时,只需要进行base[1][1]的求和即可

涉及重载运算符,代码细节多

# include<iostream>
# include<cstring>
# include<vector>
# include<math.h>

# include<algorithm>

using namespace std;

# define mod 1000000007
typedef long long int ll;

struct MAT
{

    ll mat[3][3]={0};  
    

    void init()
    {
        mat[1][1]=mat[2][2]=1;

        mat[1][2]=mat[2][1]=0;//这一行必须有,没有就会错,之所以会错,是因为init不仅要承担0矩阵初始化为0级幂矩阵的任务还承担的降幂的任务
        

    }

}sum[100000*4+10],lazy[100000*4+10];




MAT operator*(MAT a, MAT b)
{
    MAT c;

    memset(c.mat,0,sizeof(c.mat));

    for(int i=1;i<=2;i++)
    {
        for(int j=1;j<=2;j++)
        {
            for(int k=1;k<=2;k++)
            {
                c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j]%mod)%mod;

            }
        }
    }

    return c;




}

MAT operator+ (MAT a, MAT b)
{
    MAT c;

    memset(c.mat,0,sizeof(c.mat));


    for(int i=1;i<=2;i++)
    {
        for(int j=1;j<=2;j++)
        {
            c.mat[i][j]=(a.mat[i][j]+b.mat[i][j])%mod;

        }
    }

    return c;

}

MAT quickpow(ll pow)
{
    MAT c;

    c.init();

    MAT base;

    base.mat[1][1]=base.mat[1][2]=base.mat[2][1]=1;

    base.mat[2][2]=0;


    while(pow)
    {
        if(pow&1)
            c=c*base;

            pow>>=1;

            base=base*base;

    }
    return c;

}
void pushup(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];

}
void pushdown(int rt)  //懒标记的下传实际上是幂级的累加,幂级的累加靠乘法来实现
{

   sum[rt<<1]=sum[rt<<1]*lazy[rt];

   sum[rt<<1|1]=sum[rt<<1|1]*lazy[rt];


   lazy[rt<<1]=lazy[rt<<1]*lazy[rt];

   lazy[rt<<1|1]=lazy[rt<<1|1]*lazy[rt];

   lazy[rt].init();  //幂级归零

}

void build(int l,int r,int rt)
{
    sum[rt].init();

    lazy[rt].init();

    if(l==r)
    {
        ll x;

        cin>>x;

        sum[rt]=quickpow(x-1);   //f(x)为x-1次幂的base数组

        return ;


    }

    int mid=(l+r)>>1;

    build(l,mid,rt<<1);

    build(mid+1,r,rt<<1|1);

    pushup(rt);

}

void change(int L,int R,int l,int r,int rt,MAT x)  //把矩阵块累加到区间
{

    if(L<=l&&r<=R)
    {

        lazy[rt]=lazy[rt]*x;


        sum[rt]=sum[rt]*x;

        return;

    }

    pushdown(rt);

    int mid=(l+r)>>1;

    if(L<=mid)
    change(L,R,l,mid,rt<<1,x);

    if(R>mid)
        change(L,R,mid+1,r,rt<<1|1,x);


    pushup(rt);


}

ll getsum(int L,int R,int l,int r,int rt)
{

    if(L<=l&&r<=R)
    {

        return sum[rt].mat[1][1]%mod;


    }

    pushdown(rt);

    int mid=(l+r)>>1;


    ll ans=0;

    if(L<=mid)
        ans=(ans+getsum(L,R,l,mid,rt<<1))%mod;

    if(R>mid)
        ans=(ans+getsum(L,R,mid+1,r,rt<<1|1))%mod;


    return ans;


}
int main ()
{


       int n,m;

       cin>>n>>m;


       build(1,n,1);

       while(m--)
       {
           int a;

           cin>>a;

           if(a==1)
           {
               ll l,r,x;

               cin>>l>>r>>x;

               MAT y=quickpow(x);

               change(l,r,1,n,1,y);

           }
           else
           {
               int l,r;

               cin>>l>>r;

               cout<<getsum(l,r,1,n,1)<<'\n';

           }
       }


    return 0;

}

例题四

​​​​​​区间加区间sin和

根据公式

sin(x+a) = sina cosx + sinx cosa

cos (x+a) =cos a cos x +sinx sin a

且易发现,对一个区间每个数加a,再根据公式求sin 与先求sin之和再根据公式求sin结果相同

故可以利用线段树进行求解。懒标记是所加的a,懒标记的下传方式需要按照公式

# include<iostream>
# include<cstring>
# include<vector>
# include<math.h>
# include<algorithm>
using namespace std;
# define mod 1000000007
typedef long long int ll;

double sumsin[200000*4+10],sumcos[200000*4+10],lazy[200000*4+10];
/*

  sin(a+x)  = sina cosx + sinx cosa

  cos(a+x)  =cosa cosx -sina sinx


*/

void pushup(int rt)
{
    sumcos[rt]=sumcos[rt<<1]+sumcos[rt<<1|1];

    sumsin[rt]=sumsin[rt<<1]+sumsin[rt<<1|1];

}

void push(double la,int rt)
{
    double temsin=sumsin[rt];

    double temcos=sumcos[rt];

    sumsin[rt]=sin(la)*temcos+cos(la)*temsin;

    sumcos[rt]=temcos*cos(la)-sin(la)*temsin;


}
void pushdown(int rt)
{

    if(lazy[rt])  //进行下传
    {

        push(lazy[rt],rt<<1);


        push(lazy[rt],rt<<1|1);


        lazy[rt<<1]+=lazy[rt];

        lazy[rt<<1|1]+=lazy[rt];

        lazy[rt]=0;


    }


}
void build(int l,int r,int rt)
{
     if(l==r)
     {
         double  x;

         cin>>x;

         sumsin[rt]=sin(x);

         sumcos[rt]=cos(x);

         return ;

     }

     int mid=(l+r)>>1;


     build(l,mid,rt<<1);

     build(mid+1,r,rt<<1|1);

     pushup(rt);

}

void change(int L,int R,int l,int r,int rt,double x)
{
    if(L<=l&&r<=R)
    {

        push(x,rt);

        lazy[rt]+=x;

        return ;

    }

    int mid=(l+r)>>1;


    pushdown(rt);

    if(L<=mid)
        change(L,R,l,mid,rt<<1,x);

    if(R>mid)
        change(L,R,mid+1,r,rt<<1|1,x);

    pushup(rt);

}
double querysum(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        return sumsin[rt];

    }

    int mid=(l+r)>>1;


    pushdown(rt);


    double ans=0;


    if(L<=mid)

        ans+=querysum(L,R,l,mid,rt<<1);

    if(R>mid)
        ans+=querysum(L,R,mid+1,r,rt<<1|1);

    return ans;



}

int main ()
{


   int n;

   cin>>n;


   build(1,n,1);

   int t;

   cin>>t;

   while(t--)
   {
       int a;

       cin>>a;

       if(a==1)
       {

           int l,r,x;

           cin>>l>>r>>x;


           change(l,r,1,n,1,x);

       }
       else
       {
           int l,r;

           cin>>l>>r;

           cout<<querysum(l,r,1,n,1)<<endl;

       }
   }



    return 0;

}

高斯消元

为线性代数在计算机编码中的应用。

常见的形式为求解 线性方程组

ax+by+cz= A

dx+ey+fz=B

gx+hy+iz=C

求解出 x,y,z

名词 系数矩阵

\bigl(\begin{smallmatrix} a &b &c \\ d &e &f \\ g & h& i \end{smallmatrix}\bigr)  

增广矩阵

\begin{pmatrix} a &b & c &A \\ d& e& f& B\\ g& h & i & C \end{pmatrix}

利用高斯消元可以将此线性方程组进行求解

常见的高斯消元有四大类  整数解型,浮点数解型,取模型,异或型。

整形高斯消元

int a[50][50];
int x[50];


int gcd(int x,int y)
{
    return !x?x:gcd(y,x%y);

}
int lcm(int x,int y)
{
    return x/gcd(x,y)*y;

}
int Gauss(int hang,int lie)
{
    for(int i=0;i<=lie;i++)
    {
        x[i]=0;
    }

    int row=0,col=0;

    for(row=0;row<hang&&col<lie;col++,row++)
    {

        int maxrow=row;

        for(int i=row+1;i<hang;i++)
        {
            if(abs(a[i][col])>abs(a[maxrow][col]))
                maxrow=i;

        }

        if(maxrow!=row)
        {

            for(int j=col;j<=lie;j++)
            {
                swap(a[row][j],a[maxrow][j]);

            }
        }

        if(a[row][col]==0)
        {
            row--;

            continue;

        }

        for(int i=row+1;i<hang;i++)
        {
            if(a[i][col]!=0)
            {
                int LCM=lcm(abs(a[i][col]),abs(a[row][col]));

                int ta=LCM/abs(a[i][col]);
                int tb=LCM/abs(a[row][col]);

                if(a[i][col]*a[row][col]<0)
                    tb=-tb;

                for(int j=col;j<=lie;j++)
                {
                    a[i][j]=a[i][j]*ta-a[row][j]*tb;

                }
            }
        }
    }
    
    for(int i=row;i<hang;i++)
    {
        if(a[i][col])
            return -1;   //无解
        
    }
    
    int temp=hang-row;
    
    if(row<hang)
        return temp;   //自由元
        
    for(int i=hang-1;i>=0;i--)
    {
        
        int temp=a[i][lie];
        
        for(int j=i+1;j<lie;j++)
        {
            if(a[i][j])
            {
                temp-=a[i][j]*x[j];   //该行j列系数和第j解
                
            }
            
        }
        
        if(temp%a[i][i])
            return -2;    //有解但无整数解
        
        x[i]=temp/a[i][i];
        
        
    }
    
    return  0;
    
    
}

浮点型高斯消元

例题

 例题     ​​​​​​【模板】高斯消元法 - 洛谷

细节为EPS的设定

# include<iostream>
# include<cstring>
# include<vector>
# include<iomanip>
# include<queue>
# include<set>
# include<math.h>
# include<algorithm>
using namespace std;
# define mod 998244353
typedef __int128 ll;

double  a[110][110];
double  x[110];


bool check(double x)
{
    return fabs(x)>1e-6;

}
int Gauss(int hang,int lie)
{
    for(int i=0;i<=lie;i++)
    {
        x[i]=0;
    }

    int row=0,col=0;

    for(row=0;row<hang&&col<lie;col++,row++)
    {

        int maxrow=row;

        for(int i=row+1;i<hang;i++)
        {
            if(fabs(a[i][col])>fabs(a[maxrow][col]))
                maxrow=i;

        }

        if(maxrow!=row)
        {

            for(int j=col;j<=lie;j++)
            {
                swap(a[row][j],a[maxrow][j]);

            }
        }

        if(!check(a[row][col]))
        {
            row--;

            continue;

        }

        for(int i=row+1;i<hang;i++)
        {
            if(check(a[i][col]))
            {

              double ji=a[i][col]/a[row][col];


                for(int j=col;j<=lie;j++)
                {
                    a[i][j]-=a[row][j]*ji;


                }

                a[i][col]=0;

            }
        }
    }

    for(int i=row;i<hang;i++)
    {
        if(check(a[i][col]))
            return -1;   //无解

    }

    int temp=hang-row;

    if(row<hang)
        return temp;   //自由元

    for(int i=hang-1;i>=0;i--)
    {

        double  tem=a[i][lie];

        for(int j=i+1;j<lie;j++)
        {
            if(a[i][j])
            {
                tem-=a[i][j]*x[j];   //该行j列系数和第j解

            }

        }



        x[i]=tem/a[i][i];


    }

    return  0;


}
int main()
{


      int n;

      cin>>n;


      for(int i=0;i<n;i++)
      {
          for(int j=0;j<=n;j++)
          {
              cin>>a[i][j];

          }
      }


     if(Gauss(n,n))
     {
         cout<<"No Solution";

     }
     else
     {
         for(int i=0;i<n;i++)
         {
             cout<<fixed<<setprecision(2)<<x[i]<<endl;

         }
     }



    return 0;
}

模数型高斯消元

int a[100][100];

int x[100];

int gcd(int a,int b)
{
    return !b?a:gcd(b,a%b);

}
int lcm(int a,int b)
{
    return a/gcd(a,b)*b;

}
int gauss(int hang,int lie)
{
    for(int i=0;i<=lie;i++)
    {
        x[i]=0;

    }
    int col=0,row=0;

    for(row=0;row<hang&&col<lie;row++,col++)
    {

        int maxrow=row;

        for(int i=row+1;i<hang;i++)
        {
            if(abs(a[i][col])>abs(a[maxrow][col]))
                maxrow=i;

        }

        if(maxrow!=row)
        {
            for(int j=col;j<=lie;j++)
            {
                swap(a[row][j],a[maxrow][j]);

            }
        }

        if(a[row][col]==0)
        {
            row--;

            continue;
        }

        for(int i=row+1;i<hang;i++)
        {
            if(a[i][col]!=0)
            {
                int lc=lcm(abs(a[i][col]),abs(a[row][col]));

                int ta=lc/abs(a[i][col]);

                int tb=lc/abs(a[row][col]);

                if(a[i][col]*a[row][col]<0)
                    tb=-tb;

                for(int j=col;j<=lie;j++)
                {
                    a[i][j]=((a[i][j]*ta-a[row][j]*tb)%mod+mod)%mod;

                }
            }
        }
    }


    for(int i=row;i<hang;i++)
    {
        if(a[i][col])
            return  -1;

    }

    int temp=hang-row;

    if(row<hang)
        return temp;


    for(int i=hang-1;i>=0;i--)
    {
        int temp=a[i][lie];


        for(int j=i+1;j<lie;j++)
        {
            if(a[i][j])
            {
                temp-=a[i][j]*x[j];

                temp=(temp%mod+mod)%mod;

            }
        }


        while(temp%a[i][i])
        {
            temp+=mod;

        }

        x[i]=(temp/a[i][i])%mod;

    }

    return  0;


}

 异或型高斯消元

通常其系数矩阵为01,求出的解集也是01的形式

int a[100][100];

int x[100];


int gauss(int hang,int lie)
{
    for(int i=0;i<=lie;i++)
    {
        x[i]=0;
        
    }
    
    int col=0,row=0;
    
    for(row=0;row<hang&&col<lie;row++,col++)
    {
        int maxrow=row;
        
        for(int i=row+1;i<hang;i++)
        {
            if(abs(a[i][col])>abs(a[maxrow][col]))
                maxrow=i;
            
        }
        
        if(maxrow!=row)
        {
            for(int j=col;j<=lie;j++)
            {
                swap(a[row][j],a[maxrow][j]);
                
            }
        }
        
        if(a[row][col]==0)
        {
            row--;
            
            continue;
            
        }
        
        for(int i=row+1;i<hang;i++)
        {
            if(a[i][col])
            {
                for(int j=col;j<=lie;j++)
                {
                    a[i][j]^=a[row][j];
                    
                }
            }
        }
    }
    
    for(int i=row;i<hang;i++)
    {
        if(a[i][col])
            return -1;
        
    }
    
    int temp=hang-row;
    
    if(row<hang)
    return temp;
    
    
    for(int i=hang-1;i>=0;i--)
    {
        x[i]=a[i][lie];
        
        for(int j=i+1;j<lie;j++)
        {
            x[i]^=(a[i][j]&&x[j]);
            
        }
        
        //异或之后x[i]==(a[i][i]&&x[i])  如果是1,那么x[i]必须是1,如果是0,那么要具体看题意再进行分析
        
    }

    return  0;
    

}

例题

EXTENDED LIGHTS OUT

典型例题,开关灯问题

 以3*3灯为例,研究第一盏灯

L1 ^ (   A(1,1)&&X(1)  )  ^   (   A(1,2)&&X(2)  ) ^.....(   A(1,9)&&X(9)  )  =0

L为初始状态  A(x,y)为 第y盏灯的开关是否对第x盏灯有影响  X为这盏灯是否按下

其异或结果为0才能保证最终第一站灯为熄灭状态  

而我们对左边异或L1

(   A(1,1)&&X(1)  )  ^   (   A(1,2)&&X(2)  ) ^.....(   A(1,9)&&X(9)  )   =L1

类似处理其余8个灯,以A为系数矩阵,(A,L)为增广矩阵,求出X即可

# include<iostream>
# include<cstring>
# include<vector>
# include<iomanip>
# include<queue>
# include<set>
# include<math.h>
# include<algorithm>
using namespace std;
# define mod 998244353
typedef __int128 ll;

int getid(int x,int y)
{
    return x*6+y;


}

int a[50][50];

int x[50];

int gauss(int hang,int lie)
{
    for(int i=0;i<=lie;i++)
    {
        x[i]=0;

    }

    int row=0,col=0;

    for(row=0;row<hang&&col<lie;row++,col++)
    {

        int maxrow=row;

        for(int i=row+1;i<hang;i++)
        {
            if(a[i][col]>a[maxrow][col])
            {
                maxrow=i;

            }
        }


        if(maxrow!=row)
        {


        for(int j=col;j<=lie;j++)
        {
            swap(a[row][j],a[maxrow][j]);

        }

        }


        if(a[row][col]==0)
        {
            row--;

            continue;

        }



        for(int i=row+1;i<hang;i++)
        {
            if(a[i][col])
            {
                for(int j=col;j<=lie;j++)
                {
                    a[i][j]^=a[row][j];

                }
            }
        }

    }


    for(int i=hang-1;i>=0;i--)
    {
        x[i]=a[i][lie];

        for(int j=i+1;j<lie;j++)
        {
            x[i]^=(a[i][j]&&x[j]);

        }



    }
    
    
    return 0;
    
}
int main()
{




    int t;

    cin>>t;

    int cnt=1;

    while(t--)
    {

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

        for(int i=0; i<30; i++)
        {
            cin>>a[i][30];

        }


        for(int i=0; i<5; i++)
        {
            for(int j=0; j<6; j++)
            {
               int t=i*6+j;
               a[t][t]=1;


                if(i>0)
                    a[(i-1)*6+j][t]=1;

                if(i<4)
                    a[(i+1)*6+j][t]=1;

                if(j>0)
                    a[i*6+j-1][t]=1;

                if(j<5)
                    a[i*6+j+1][t]=1;

            }
        }


        gauss(30,30);

        int mo=5;


        cout<<"PUZZLE #"<<cnt<<endl;

        for(int i=0;i<30;i++)
        {
           cout<<x[i]<<" ";

           if(i&&i%mo==0)
           {
               cout<<endl;

               mo+=6;
           }
        }


        cnt++;


    }




    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qinsanma and Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值