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; }