BZOJ 3168 [Heoi2013]钙铁锌硒维生素 ——矩阵乘法 矩阵求逆

考虑向量ai能否换成向量bj

首先ai都是线性无关的,然后可以a线性表出bj c1*a1+c2*a2+...=bj

然后移项,得 c1/ci*a1+...-1/ci*bj+...=ai

所以当ci不为0得时候是可以替换的,

所以C*A=B 若c[i][j]!=0 那么ai可以换成bj

然后求逆计算。

关于字典序最小得最大匹配。在做完最大匹配之后,从前往后找不影响前面得交错路进行修改即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define F(i,j,k) for (ll i=j;i<=k;++i)
#define D(i,j,k) for (ll i=j;i>=k;--i)
#define ll long long
 
const ll md=999911657;
ll n;
 
struct matrix{
    ll x[305][305];
    void init(){memset(x,0,sizeof x);}
    matrix operator * (const matrix & a ) const{
        matrix ret;
        ret.init();
        F(i,1,n) F(j,1,n)
        {
            F(k,1,n) ret.x[i][j]=ret.x[i][j]+x[i][k]*a.x[k][j];
            ret.x[i][j]%=md;
        }
        return ret;
    }
    void build()
    {
        init();
        F(i,1,n) x[i][i]=1;
    }
    void read()
    {F(i,1,n)F(j,1,n)scanf("%lld",&x[i][j]);}
}A,B,C,Ainv;
 
ll qpow(ll a,ll b)
{
    ll ret=1;
    while (b)
    {
        if (b&1) (ret*=a)%=md;
        (a*=a)%=md;
        b>>=1;
    }
    return ret;
}
 
matrix gauss(matrix & x)
{
    matrix E; E.build();int i,j,k;
    for (i=1;i<=n;++i)
    {
        for (k=i;k<=n;++k) if (x.x[k][i]) break;
        for (j=1;j<=n;++j) swap(x.x[i][j],x.x[k][j]),swap(E.x[i][j],E.x[k][j]);
        ll inv=qpow(x.x[i][i],md-2);
        for (j=1;j<=n;++j)
        {
            x.x[i][j]=x.x[i][j]*inv%md;
            E.x[i][j]=E.x[i][j]*inv%md;
        }
        for (k=1;k<=n;++k)
            if (k!=i)
            {
                ll tmp=(md-x.x[k][i]%md)%md;
                for (j=1;j<=n;++j)
                {
                    x.x[k][j]=(x.x[k][j]+x.x[i][j]*tmp)%md;
                    E.x[k][j]=(E.x[k][j]+E.x[i][j]*tmp)%md;
                }
            }
    }
    return E;
}
 
int map[305][305],vis[305],linker[305];
 
bool dfs(int o)
{
    F(i,1,n)if (map[o][i]&&!vis[i])
    {
        vis[i]=1;
        if (!linker[i]||dfs(linker[i]))
        {
            linker[i]=o;
            return true;
        }
    }
    return false;
}
 
int dfs2(int o,int from)
{
    for (int i=1;i<=n;++i)
        if (map[o][i]&&!vis[i])
        {
            vis[i]=1;
            if (linker[i]==from||linker[i]>from&&dfs2(linker[i],from))
            {
                linker[i]=o;
                return true;
            }
        }
    return false;
}
 
int main()
{
    scanf("%lld",&n);
    A.read();B.read();Ainv=gauss(A);
    C=B*Ainv;
    F(i,1,n) F(j,1,n) if (C.x[i][j]) map[j][i]=1;
    F(i,1,n)
    {
        memset(vis,0,sizeof vis);
        if (!dfs(i))
        {
            printf("NIE\n");
            return 0;
        }
    }
    F(i,1,n)
    {
        memset(vis,0,sizeof vis);
        dfs2(i,i);
    }
    printf("TAK\n");
    F(i,1,n)F(j,1,n)if (linker[j]==i)printf("%d\n",j);
    return 0;
}

  

posted @ 2017-03-19 20:31  SfailSth  阅读(157)  评论(0编辑  收藏  举报