// iostream is too mainstream
#include <cstdio>
// bitch please
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <list>
#include <cmath>
#include <iomanip>
#define dibs reserve
#define OVER9000 1234567890
#define ALL_THE(CAKE,LIE) for(auto LIE =CAKE.begin(); LIE != CAKE.end(); LIE++)
#define tisic 47
#define soclose 1e-8
#define chocolate win
// so much chocolate
#define patkan 9
#define ff first
#define ss second
#define abs(x) ((x < 0)?-(x):x)
#define uint unsigned int
#define dbl long double
using namespace std;
// mylittledoge
 
int gcd(int x, int y) {
    if(x > y) swap(x,y);
    while(x > 0) {
        int z =x;
        x =y%x;
        y =z;}
    return y;}
 
int main() {
    cin.sync_with_stdio(0);
    cin.tie(0);
    int N;
    cin >> N;
    vector< vector<int> > H(N,vector<int>(N));
    vector< vector<int> > V =H;
    for(int i =0; i < N*N; i++) cin >> H[i/N][i%N];
    for(int i =0; i < N*N; i++) cin >> V[i/N][i%N];

    queue< pair<int,int> > q;
    int dx[] ={1,-1,0,0};
    int dy[] ={0,0,1,-1};
    int C =0;
    vector< vector<int> > isC(N,vector<int>(N,-1));
    vector<int> sC;
    for(int i =0; i < N; i++) for(int j =0; j < N; j++) if(isC[i][j] == -1) {
        q.push(make_pair(i,j));
        isC[i][j] =C;
        int s =1;
        while(!q.empty()) {
            int x =q.front().ff, y =q.front().ss;
            for(int k =0; k < 4; k++) if(max(dx[k]+x,dy[k]+y) < N && min(dx[k]+x,dy[k]+y) >= 0)
                if(isC[dx[k]+x][dy[k]+y] == -1 && V[x][y] == V[dx[k]+x][dy[k]+y] && H[x][y] == H[dx[k]+x][dy[k]+y]) {
                    isC[dx[k]+x][dy[k]+y] =C;
                    s++;
                    q.push(make_pair(dx[k]+x,dy[k]+y));}
            q.pop();}
        sC.push_back(s);
        C++;}
    
    map< pair<int,int>, int> T;
    vector< vector< pair<int,int> > > G0;
    G0.dibs(100000);
    for(int i =0; i < N; i++) for(int j =0; j < N; j++) for(int k =0; k < 4; k++)
        if(max(dx[k]+i,dy[k]+j) < N && min(dx[k]+i,dy[k]+j) >= 0)
            if(isC[i][j] != isC[i+dx[k]][j+dy[k]]) {
                int a =H[i][j]-H[i+dx[k]][j+dy[k]];
                int b =-V[i][j]+V[i+dx[k]][j+dy[k]];
                if(b == 0) continue;
                if(b < 0) a *=-1, b *=-1;
                int d =gcd(abs(a),b);
                if(a < 0) continue;
                int t =(T.find(make_pair(a/d,b/d)) == T.end())?T.size():T[make_pair(a/d,b/d)];
                T[make_pair(a/d,b/d)] =t;
				G0.resize(max((int)G0.size(),t+1));
				G0[t].push_back(make_pair(isC[i][j],isC[i+dx[k]][j+dy[k]]));}
 
    int ans =0;
    queue<int> qq;
    vector<bool> vis(C,false);
    vector< vector<int> > G(C);
	vector<int> vv;
	for(int t =0; t < G0.size(); t++) {
	    ALL_THE(G0[t],jt) {
   			G[jt->ff].push_back(jt->ss);
   			G[jt->ss].push_back(jt->ff);}
   		ALL_THE(G0[t],jt) if(!vis[jt->ff]) {
   			int akt =0;
   			qq.push(jt->ff);
	   		vis[qq.front()] =true;
    		while(!qq.empty()) {
    			akt +=sC[qq.front()];
    			vv.push_back(qq.front());
    			ALL_THE(G[qq.front()],kt) if(!vis[*kt]) {
    				vis[*kt] =true;
    				qq.push(*kt);}
    			qq.pop();}
    		ans =max(ans,akt);}
    	ALL_THE(G0[t],jt) {
    		G[jt->ff].clear();
    		G[jt->ss].clear();}
    	ALL_THE(vv,jt) vis[*jt] =false;
    	vv.clear();}

    cout << ans << "\n";
    return 0;}
 
// look at my code
// my code is amazing