結果
問題 | No.2446 完全列 |
ユーザー |
👑 ![]() |
提出日時 | 2023-08-26 01:00:09 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 70 ms / 2,000 ms |
コード長 | 13,321 bytes |
コンパイル時間 | 368 ms |
コンパイル使用メモリ | 82,792 KB |
実行使用メモリ | 67,968 KB |
最終ジャッジ日時 | 2024-12-24 14:23:51 |
合計ジャッジ時間 | 3,234 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 30 |
ソースコード
from copy import deepcopyclass Modulo_Matrix():__slots__=("ele","row","col","size")#入力def __init__(self,M):""" 行列 M の定義M: 行列※ Mod: 法はグローバル変数から指定"""self.ele=[[x%Mod for x in X] for X in M]R=len(M)if R!=0:C=len(M[0])else:C=0self.row=Rself.col=Cself.size=(R,C)#出力def __str__(self):return "["+"\n".join(map(str,self.ele))+"]"def __repr__(self):return str(self)#+,-def __pos__(self):return selfdef __neg__(self):return self.__scale__(-1)#加法def __add__(self,other):M=self.ele; N=other.eleL=[[0]*self.col for _ in range(self.row)]for i in range(self.row):Li,Mi,Ni=L[i],M[i],N[i]for j in range(self.col):Li[j]=Mi[j]+Ni[j]return Modulo_Matrix(L)def __iadd__(self,other):M=self.ele; N=other.elefor i in range(self.row):Mi,Ni=M[i],N[i]for j in range(self.col):Mi[j]+=Ni[j]Mi[j]%=Modreturn self#減法def __sub__(self,other):M=self.ele; N=other.eleL=[[0]*self.col for _ in range(self.row)]for i in range(self.row):Li,Mi,Ni=L[i],M[i],N[i]for j in range(self.col):Li[j]=Mi[j]-Ni[j]return Modulo_Matrix(L)def __isub__(self,other):M=self.ele; N=other.elefor i in range(self.row):Mi,Ni=M[i],N[i]for j in range(self.col):Mi[j]-=Ni[j]Mi[j]%=Modreturn self#乗法def __mul__(self,other):if isinstance(other,Modulo_Matrix):assert self.col==other.row, "左側の列と右側の行が一致しません.({},{})".format(self.size,other.size)M=self.ele; N=other.eleE=[[0]*other.col for _ in range(self.row)]for i in range(self.row):Ei,Mi=E[i],M[i]for k in range(self.col):m_ik,Nk=Mi[k],N[k]for j in range(other.col):Ei[j]+=m_ik*Nk[j]Ei[j]%=Modreturn Modulo_Matrix(E)elif isinstance(other,int):return self.__scale__(other)def __rmul__(self,other):if isinstance(other,int):return self.__scale__(other)def inverse(self):assert self.row==self.col,"正方行列ではありません."M=selfN=M.rowR=[[1 if i==j else 0 for j in range(N)] for i in range(N)]T=deepcopy(M.ele)for j in range(N):if T[j][j]==0:for i in range(j+1,N):if T[i][j]:breakelse:assert 0, "正則行列ではありません"T[j],T[i]=T[i],T[j]R[j],R[i]=R[i],R[j]Tj,Rj=T[j],R[j]inv=pow(Tj[j], Mod-2, Mod)for k in range(N):Tj[k]*=inv; Tj[k]%=ModRj[k]*=inv; Rj[k]%=Modfor i in range(N):if i==j: continuec=T[i][j]Ti,Ri=T[i],R[i]for k in range(N):Ti[k]-=Tj[k]*c; Ti[k]%=ModRi[k]-=Rj[k]*c; Ri[k]%=Modreturn Modulo_Matrix(R)#スカラー倍def __scale__(self,r):M=self.eler%=ModL=[[(r*M[i][j])%Mod for j in range(self.col)] for i in range(self.row)]return Modulo_Matrix(L)#累乗def __pow__(self,n):assert self.row==self.col, "正方行列ではありません."r=self.coldef __mat_mul(A,B):E=[[0]*r for _ in range(r)]for i in range(r):a=A[i]; e=E[i]for k in range(r):b=B[k]for j in range(r):e[j]+=a[k]*b[j]e[j]%=Modreturn EX=deepcopy(self.ele)E=[[1 if i==j else 0 for j in range(r)] for i in range(r)]sgn=1 if n>=0 else -1n=abs(n)while True:if n&1:E=__mat_mul(E,X)n>>=1if n:X=__mat_mul(X,X)else:breakif sgn==1:return Modulo_Matrix(E)else:return Modulo_Matrix(E).inverse()#等号def __eq__(self,other):return self.ele==other.ele#不等号def __neq__(self,other):return not(self==other)#転置def transpose(self):return Modulo_Matrix(list(map(list,zip(*self.ele))))#行基本変形def row_reduce(self):M=self(R,C)=M.sizeT=[]for i in range(R):U=[]for j in range(C):U.append(M.ele[i][j])T.append(U)I=0for J in range(C):if T[I][J]==0:for i in range(I+1,R):if T[i][J]!=0:T[i],T[I]=T[I],T[i]breakif T[I][J]!=0:u=T[I][J]u_inv=pow(u, Mod-2, Mod)for j in range(C):T[I][j]*=u_invT[I][j]%=Modfor i in range(R):if i!=I:v=T[i][J]for j in range(C):T[i][j]-=v*T[I][j]T[i][j]%=ModI+=1if I==R:breakreturn Modulo_Matrix(T)#列基本変形def column_reduce(self):M=self(R,C)=M.sizeT=[]for i in range(R):U=[]for j in range(C):U.append(M.ele[i][j])T.append(U)J=0for I in range(R):if T[I][J]==0:for j in range(J+1,C):if T[I][j]!=0:for k in range(R):T[k][j],T[k][J]=T[k][J],T[k][j]breakif T[I][J]!=0:u=T[I][J]u_inv=pow(u, Mod-2, Mod)for i in range(R):T[i][J]*=u_invT[i][J]%=Modfor j in range(C):if j!=J:v=T[I][j]for i in range(R):T[i][j]-=v*T[i][J]T[i][j]%=ModJ+=1if J==C:breakreturn Modulo_Matrix(T)#行列の階数def rank(self):M=self.row_reduce()(R,C)=M.sizeT=M.elernk=0for i in range(R):f=Falsefor j in range(C):if T[i][j]!=0:f=Truebreakif f:rnk+=1else:breakreturn rnk#行の結合def row_union(self,other):return Modulo_Matrix(self.ele+other.ele)#列の結合def column_union(self,other):E=[]for i in range(self.row):E.append(self.ele[i]+other.ele[i])return Modulo_Matrix(E)def __getitem__(self,index):if isinstance(index, int):return self.ele[index]else:return self.ele[index[0]][index[1]]def __setitem__(self,index,val):assert isinstance(index,tuple) and len(index)==2self.ele[index[0]][index[1]]=val#==================================================class Modulo_Vector:def __init__(self, vector):self.vec = [vi % Mod for vi in vector]self.size = len(vector)#出力def __str__(self):return str(self.vec)def __repr__(self):return str(self)def __bool__(self):return any(self.vec)def __iter__(self):yield from self.vec#+,-def __pos__(self):return selfdef __neg__(self):return self.__scale__(-1)#加法def __add__(self, other):assert self.size == other.size, f"2つのベクトルのサイズが異なります. ({self.size}, {other.size})"return Modulo_Vector([vi + wi for vi, wi in zip(self, other)])#減法def __sub__(self, other):return self+(-other)def __rsub__(self, other):return (-self)+other#乗法def __mul__(self,other):passdef __rmul__(self,other):return self.__scale__(other)#スカラー倍def __scale__(self, r):return Modulo_Vector([r * vi for vi in self])#内積def inner(self,other):assert self.size == other.size, f"2つのベクトルのサイズが異なります. ({self.size}, {other.size})"return sum(vi * wi % Mod for vi, wi in zip(self, other)) % Mod#累乗def __pow__(self,n):pass#等号def __eq__(self, other):return self.vec == other.vecdef __len__(self):return self.size#不等号def __neq__(self, other):return not (self == other)def __getitem__(self,index):assert isinstance(index,int)return self.vec[index]def __setitem__(self,index,val):assert isinstance(index,int)self.vec[index]=valclass Modulo_Vector_Space:def __init__(self, dim):""" 次元が dim のベクトル空間の部分空間を生成する."""self.dim=dimself.basis=[]self.__ind=[]def __contains__(self, v):for i,u in zip(self.__ind, self.basis):v-=v[i]*ureturn not bool(v)def add_vectors(self, *S):for v in S:assert len(v)==self.dimfor i,u in zip(self.__ind, self.basis):v-=v[i]*uif bool(v):for j in range(self.dim):if v[j]:self.__ind.append(j)breakv=pow(v[j], Mod-2, Mod) * vself.basis.append(v)for k in range(len(self.basis)-1):self.basis[k]-=self.basis[k][j]*vdef dimension(self):return len(self.basis)def __le__(self, other):for u in self.basis:if u not in other:return Falsereturn Truedef __ge__(self, other):return other<=selfdef __eq__(self, other):return (self<=other) and (other<=self)def refresh(self):I=sorted(range(len(self.__ind)), key=lambda i:self.__ind[i])self.basis=[self.basis[i] for i in I]self.__ind=[self.__ind[i] for i in I]def projection(self, v):for i,u in zip(self.__ind, self.basis):v-=v[i]*ureturn vdef Kernel_Space(A):""" 行列 A の核空間 Ker A (Ax=0 となる x の空間) を求める."""row,col=A.sizeT=deepcopy(A.ele)p=[]; q=[]rnk=0for j in range(col):for i in range(rnk,row):if T[i][j]!=0:breakelse:q.append(j)continueif j==col:return Modulo_Vector_Space(col)p.append(j)T[rnk],T[i]=T[i],T[rnk]inv=pow(T[rnk][j], Mod-2, Mod)for k in range(col):T[rnk][k]=(inv*T[rnk][k])%Modfor s in range(row):if s==rnk:continuec=-T[s][j]for t in range(col):T[s][t]=(T[s][t]+c*T[rnk][t])%Modrnk+=1x=[0]*colfor i in range(rnk):x[p[i]]=T[i][-1]ker_dim=col-rnkker=[[0]*col for _ in range(ker_dim)]for i in range(ker_dim):ker[i][q[i]]=1for i in range(ker_dim):for j in range(rnk):ker[i][p[j]]=-T[j][q[i]]%ModKer=Modulo_Vector_Space(col)Ker.add_vectors(*[Modulo_Vector(v) for v in ker])return Kerdef Column_Vector(A):""" 行列 A の列ベクトルを生成する.A: Modulo_Matrix"""return [Modulo_Vector(v) for v in zip(*A.ele)]def Image_Space(A):""" A の像空間 Im A を求める."""V=Modulo_Vector_Space(A.row)V.add_vectors(*Column_Vector(A))return V#==================================================def solve():L, M, N = map(int, input().split())A = [None] * Lfor i in range(L):A[i] = list(map(int, input().split()))B = [None] * Mfor i in range(M):B[i] = list(map(int, input().split()))def calc(mod):global Mod; Mod = modX = Modulo_Matrix(A)Y = Modulo_Matrix(B)return Image_Space(Y) == Kernel_Space(X)return all(calc(mod) for mod in [998244353, 10**9 + 7, 10**9 + 9, 17737, 17747, 17749])#==================================================print("Yes" if solve() else "No")