Matrix Equation (2020icpc济南)

A、Matrix Equation

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

思路:
首先,考虑 (C) 矩阵的元素只由$ 0 1 $组成,每个 (C) 矩阵中的未知数都可以通过 (A、B) 两个矩阵表示成一些方程组,考虑高斯消元法,那么即如果某个位置都未知数是确定的,则方法数不变,如果是自由变元,即不能确定的,那么方法数$ imes 2$(因为该位置有两种可能取值,即0或1)。
在使用高斯消元法求解过程中,我们发现如果设置 (n imes n) 个未知量,那么时间复杂度必定会爆炸,接下来考虑上面都式子,我们发现两个式子都是列独立的,即 (C) 中每一列的所有未知量可以单独构成n个方程组,这一列与其他列的未知量是无关的,可以推出方乘(以第一列为例)
(egin{cases}A_{1,1} imes C_{1,1}+A_{1,2} imes C_{2,1}+ ...+A_{1,n} imes C_{n,1} = B_{1,1} imes C_{1,1}\A_{2,1} imes C_{1,1}+A_{2,2} imes C_{2,1}+ ...+A_{2,n} imes C_{n,1} = B_{2,1} imes C_{2,1}\ ......\ ......\ A_{3,1} imes C_{1,1}+A_{3,2} imes C_{2,1}+ ...+A_{3,n} imes C_{n,1} = B_{n,1} imes 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
",ans);
    return 0;
}

越自律,越自由
原文地址:https://www.cnblogs.com/ha-chuochuo/p/14300360.html