zoukankan      html  css  js  c++  java
  • 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
    ");
                return 0;
            }
        }
        F(i,1,n)
        {
            memset(vis,0,sizeof vis);
            dfs2(i,i);
        }
        printf("TAK
    ");
        F(i,1,n)F(j,1,n)if (linker[j]==i)printf("%d
    ",j);
        return 0;
    }
    

      

  • 相关阅读:
    OCP-1Z0-053-V12.02-15题
    Boost.Asio性能测试
    使用asio搭建服务器
    boost::asio::ip::tcp::socket is connected?(如何知道socket的链接是链接或断开?)
    boost::async_read_some连续接收数据
    基于boost asio实现的支持ssl的通用socket框架
    Boost.Asio的使用技巧
    Matlab基本函数-expm函数
    Matlab基本函数-exp函数
    OCP-1Z0-053-V12.02-337题
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6582098.html
Copyright © 2011-2022 走看看