Matrix Equation (2020icpc济南)

A、Matrix Equation

题意:
给定两个 \(n\times n\)\(01\)矩阵\(A\),\(B\),求\(01\)矩阵 \(C\)种数,其中 \(C\) 满足 \(A\times C = B\odot C\)
\(Z = X\times Y\) ,即表示 \({Z_{i,j}} = (\sum^{n}_{k=1} X_{i,k}Y_{k,j} ) mod 2\)
\(S = X\odot Y\) ,即表示 \({S_{i,j}} = X_{i,j}Y_{i,j}\)

思路:
首先,考虑 \(C\) 矩阵的元素只由$ 0 1 $组成,每个 \(C\) 矩阵中的未知数都可以通过 \(A、B\) 两个矩阵表示成一些方程组,考虑高斯消元法,那么即如果某个位置都未知数是确定的,则方法数不变,如果是自由变元,即不能确定的,那么方法数$ \times 2$(因为该位置有两种可能取值,即0或1)。
在使用高斯消元法求解过程中,我们发现如果设置 \(n\times n\) 个未知量,那么时间复杂度必定会爆炸,接下来考虑上面都式子,我们发现两个式子都是列独立的,即 \(C\) 中每一列的所有未知量可以单独构成n个方程组,这一列与其他列的未知量是无关的,可以推出方乘(以第一列为例)
\(\begin{cases}A_{1,1}\times C_{1,1}+A_{1,2}\times C_{2,1}+ ...+A_{1,n}\times C_{n,1} = B_{1,1}\times C_{1,1}\\A_{2,1}\times C_{1,1}+A_{2,2}\times C_{2,1}+ ...+A_{2,n}\times C_{n,1} = B_{2,1}\times C_{2,1}\\ ......\\ ......\\ A_{3,1}\times C_{1,1}+A_{3,2}\times C_{2,1}+ ...+A_{3,n}\times C_{n,1} = B_{n,1}\times C_{n,1} \\\end{cases}\)
然后把右边移动到左边,由左边各未知数的系数作为增广矩阵,最后用高斯消元法,一列列的求出各列中自由变元的数量即可。
最终答案即是 \(2^{ans} \ mod \ 998244353\)

代码:

const int N = 205;
const ll mod=998244353;
ll A[N][N],B[N][N];
ll ma[N][N];
ll x[N];
ll n;
bool freeX[N];
//有equ个方程,var个变元。增广矩阵行数为equ,列数为var+1
ll Gauss(ll equ, ll val){
    ll r = 1, ans = 0;
    for(int c = 1; c <= n; c++)
    {
        ll now = r;
        for(int i = r; i <= n; i++)
        {
            if(ma[i][c])
            {
                now = i;
                break;
            }
        }
        if(!ma[now][c])  
        {
            ans++;
            continue;
        }
        for(int i = c; i <= n; i++)
            swap(ma[now][i], ma[r][i]);
        //Print(mc);
        for(int i = r + 1; i <= n; i++)
        {
            if(ma[i][c])
                for(int j = c; j <= n; j++)
                    ma[i][j] ^= ma[r][j];
        }
        //Print(mc);
        r++;
    }
    return ans;
}
 
ll qpow(ll a,ll b,ll mod)
{
    ll ans=1;
    while(b){
        if(b&1){
            ans=ans*a;
            ans=ans%mod;
        }
        a=a*a;
        a=a%mod;
        b/=2;
    }
    return ans%mod;
}
void init()
{
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            ma[i][j]=A[i][j];
        }
    }
 }
int main()
{
    ll equ,var;  //equ个方程,var个变元
    scanf("%lld",&n);
    equ=n;
    var=n;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%lld",&A[i][j]);
            ma[i][j]=A[i][j];
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%lld",&B[i][j]);
        }
    }
    ll ans=1;
    for(int j=1;j<=n;j++)
    {  
        init();
        for(int i=1;i<=n;i++){
            ma[i][i]=(A[i][i]-B[i][j]+2)%2;
            ma[i][n+1]=0;
        }
        ll freenum=Gauss(equ,var);
        if(freenum==-1) continue;
        //cout<<freenum<<endl;
        ans*=qpow(2,freenum,998244353);
        ans=ans%mod;
    }
    printf("%lld\n",ans);
    return 0;
}

posted @ 2021-01-19 21:59  hachuochuo  阅读(165)  评论(0编辑  收藏  举报