#include using namespace std; #define fo(i,j,k) for(int i=(j),end_i=(k);i<=end_i;i++) #define ff(i,j,k) for(int i=(j),end_i=(k);i< end_i;i++) #define fd(i,j,k) for(int i=(j),end_i=(k);i>=end_i;i--) #define debug(x) cerr<<#x<<"="< #define ll long long #define ull unsigned ll #define lll __int128 #define db double #define lb long db #define pb push_back #define mp make_pair #define fi first #define se second #define endl "\n" templateinline void read(T &x) { x=0; char ch=getchar(); bool f=0; for(;ch<'0'||ch>'9';ch=getchar()) f|=(ch=='-'); for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+(ch^48); if(f) x=-x; } template inline void read(T &a, V&... b){read(a); read(b...);} mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count()); const ll mod = 998244353; inline ll Pow(ll x,ll y) { ll ans = 1; for(; y; y >>= 1, x = x * x % mod) if(y & 1) ans = ans * x % mod; return ans; } inline ll Add(ll x,ll y) { x += y; return (x >= mod) ? x - mod : x; } inline ll Dec(ll x,ll y) { x -= y; return (x < 0) ? x + mod : x; } inline ll Mul(ll x,ll y) { return 1ll * x * y % mod; } const int N=502; struct matrix{ int n; ll a[N][N]; matrix(){ n = 0; memset(a,0,sizeof(a));} void clear(){ n = 0; memset(a,0,sizeof(a));} void print() { printf("%lld\n", n); fo(i,1,n) { fo(j,1,n) printf("%lld ", a[i][j]); printf("\n"); } } }; namespace Mat { static ll a[N][N],b[N][N+N],c[N][N],d[N][N]; static matrix B,C; inline ll det(const matrix &A) { // 行列式 int n=A.n; fo(i,1,n) fo(j,1,n) a[i][j]=A.a[i][j]; ll d=1,iv,tmp; fo(i,1,n) { int k=i; fo(j,i+1,n) if(a[j][i]) {k=j; break;} if(k!=i) {fo(j,i,n) swap(a[k][j],a[i][j]); d=(mod-d)%mod;} if(!a[i][i]) return 0; iv=Pow(a[i][i],mod-2); fo(j,i+1,n) { tmp=a[j][i]*iv%mod; fo(k,i,n) a[j][k]=Dec(a[j][k],a[i][k]*tmp%mod); } d=d*a[i][i]%mod; } return d; } inline matrix inv(const matrix &A) {//求逆 int n=A.n; fo(i,1,n) fo(j,1,n) b[i][j+n]=0,b[i][j]=A.a[i][j]; fo(i,1,n) b[i][i+n]=1; ll iv,tmp; fo(i,1,n) { int k=n+1; fo(j,i,n) if(b[j][i]) {k=j; break;} if(k==n+1) continue; if(k!=i) fo(j,1,n+n) swap(b[i][j],b[k][j]); iv=Pow(b[i][i],mod-2); fo(j,i+1,n) { tmp=b[j][i]*iv%mod; fo(k,i,n+n) b[j][k]=Dec(b[j][k],b[i][k]*tmp%mod); } } fd(i,n,1) { iv=Pow(b[i][i],mod-2); fo(j,i,n+n) b[i][j]=b[i][j]*iv%mod; fd(j,i-1,1) if(b[j][i]) { tmp=b[j][i]; fo(k,i,n+n) b[j][k]=Dec(b[j][k],b[i][k]*tmp%mod); } } B.clear(); B.n = n; fo(i,1,n) fo(j,1,n) B.a[i][j]=b[i][j+n]; return B; } int r(const matrix& A) { //求秩 int n=A.n; fo(i,1,n) fo(j,1,n) a[i][j]=A.a[i][j]; int d=0; ll iv,tmp; fo(i,1,n) { int k=n+1; fo(j,i,n) if(a[j][i]) {k=j; break;} if(k==n+1) continue; d++; if(k!=i) fo(j,i,n) swap(a[i][j],a[k][j]); iv=Pow(a[i][i],mod-2); fo(j,i+1,n) { tmp=a[j][i]*iv%mod; fo(k,i,n) a[j][k]=Dec(a[j][k],tmp*a[i][k]%mod); } } return d; } static ll v[N],w[N]; inline bool ins(ll *v,int n,int id,ll *ans) { fo(i,1,n) w[i]=0; w[id]=1; ll tmp; fd(i,n,1) if(v[i]) { if(!c[i][i]) { fd(j,i,1) c[i][j]=v[j]; fo(j,1,n) d[i][j]=w[j]; return 0; } tmp=Pow(c[i][i],mod-2)*v[i]%mod; fd(j,i,1) v[j]=Dec(v[j],c[i][j]*tmp%mod); fo(j,1,n) w[j]=Dec(w[j],d[i][j]*tmp%mod); } fo(i,1,n) ans[i]=w[i]; return 1; } inline void get_G(const matrix &A,ll *p) { //解齐次线性方程非零解 int n=A.n; fo(i,1,n) fo(j,1,n) a[i][j]=A.a[i][j]; memset(c,0,sizeof(c)); memset(d,0,sizeof(d)); fo(i,1,n) { fo(j,1,n) v[j]=a[j][i]; if(ins(v,n,i,p)) return; } } inline matrix solve(const matrix &A) { //求所有代数余子式 int n=A.n; int rank=r(A); if(rank == n) { ll d=det(A); B=inv(A); C.clear(); C.n = n; fo(i,1,n) fo(j,1,n) C.a[i][j]=B.a[j][i]*d%mod; return C; } else if(rank <= n-2) { C.clear(); C.n = n; return C; } else { static ll p[N],q[N]; get_G(A,q); fo(i,1,n) fo(j,1,n) B.a[j][i]=A.a[i][j]; get_G(B,p); int c=0,r=0; fo(i,1,n) if(q[i]) {c=i; break;} fo(i,1,n) if(p[i]) {r=i; break;} fo(i,1,n) if(i!=r) fo(j,1,n) if(j!=c) B.a[i-(i>r)][j-(j>c)]=A.a[i][j]; B.n = n - 1; ll d=det(B); C.clear(); C.n = n; C.a[r][c]=((r+c)%2==1)?(mod-d)%mod:d; ll iv=Pow(q[c]*p[r]%mod,mod-2); fo(i,1,n) fo(j,1,n) C.a[i][j]=C.a[r][c]*iv%mod*p[i]%mod*q[j]%mod; return C; } } } namespace Characteristic { void HessenbergReduce(matrix &A) { int n = A.n; fo(i,1,n-2) { int x = 0; fo(j,i+1,n) if (A.a[j][i]) { x = j; break; } if(!x) continue; fo(j,1,n) swap(A.a[i+1][j], A.a[x][j]); fo(j,1,n) swap(A.a[j][i+1], A.a[j][x]); ll inv = Pow(A.a[i+1][i], mod - 2); fo(j,i+2,n) { ll t = A.a[j][i] * inv % mod; fo(k,1,n) A.a[j][k] = Dec(A.a[j][k], Mul(t, A.a[i+1][k])); fo(k,1,n) A.a[k][i+1] = Add(A.a[k][i+1], Mul(t, A.a[k][j])); } } } // 返回矩阵的特征多项式的系数,即 det(xI-A) 的各项系数 vector CharacteristicPolynomial(matrix A) { int n = A.n; HessenbergReduce(A); vector> p(n+1); p[0] = {1}; ff(i,0,n) { p[i+1].assign(i + 2, 0); fo(j,0,i) p[i+1][j+1] = p[i][j]; fo(j,0,i) p[i+1][j] = Dec(p[i+1][j], Mul(A.a[i+1][i+1], p[i][j])); ll tmp = 1; fd(j,i-1,0) { tmp = Mul(tmp, A.a[j+2][j+1]); ll x = (mod - A.a[j+1][i+1]) * tmp % mod; fo(k,0,j) p[i+1][k] = Add(p[i+1][k], Mul(x, p[j][k])); } } return p[n]; } vector detPoly(matrix A, matrix B) { int n = A.n, x = 0; ll invAB = 1; fo(i,1,n) { int y = 0; fo(j,i,n) if (B.a[j][i]) { y = j; break; } if (!y) { ++x; if (x > n) return vector(n+1, 0); fo(j,1,i) { ll v = B.a[j][i]; B.a[j][i] = 0; fo(k,1,n) A.a[k][i] = Dec(A.a[k][i], Mul(v, A.a[k][j])); } fo(k,1,n) swap(A.a[k][i], B.a[k][i]); -- i; continue; } if (y != i) { invAB = mod - invAB; fo(j,1,n) swap(A.a[i][j], A.a[y][j]); fo(j,1,n) swap(B.a[i][j], B.a[y][j]); } invAB = Mul(invAB, B.a[i][i]); ll inv = Pow(B.a[i][i], mod - 2); fo(j,1,n) { A.a[i][j] = Mul(A.a[i][j], inv); B.a[i][j] = Mul(B.a[i][j], inv); } fo(j,1,n) if (j != i) { ll tmp = B.a[j][i]; fo(k,1,n) { A.a[j][k] = Dec(A.a[j][k], Mul(tmp, A.a[i][k])); B.a[j][k] = Dec(B.a[j][k], Mul(tmp, B.a[i][k])); } } } fo(i,1,n) fo(j,1,n) A.a[i][j] = mod - A.a[i][j]; auto ans = CharacteristicPolynomial(A); for (auto &x : ans) x = Mul(x, invAB); ans.erase(ans.begin(), ans.begin() + x); ans.resize(n + 1); return ans; } } int n; matrix A, B; int p[N]; int main() { read(n); A.n = B.n = n; fo(i,1,n) fo(j,1,n) read(A.a[i][j]); fo(i,1,n) fo(j,1,n) read(B.a[i][j]); auto ans = Characteristic::detPoly(A, B); fo(i,0,n) printf("%lld\n", ans[i]); return 0; }