//Author : Siriuslight
#include "bits/stdc++.h"
#include "ext/pb_ds/assoc_container.hpp"
#include "ext/pb_ds/tree_policy.hpp"
#define FIO ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0),cout<<setprecision(10)<<fixed;
#define F first
#define S second

using namespace std;
using namespace __gnu_pbds;

#define TRACE
#ifdef TRACE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << " : " << arg1 << std::endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ','); cerr.write(names, comma - names) << " : " << arg1<<" | ";__f(comma+1, args...);
}
#else
#define trace(...)
#endif

typedef long long ll;
typedef long double ld;
typedef tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update> ordered_set;

const ll inf = 1e9+100, N = 5200+5;
const ll INF = 1e18+100, MOD = 1e9+7;

ll powmod(ll a,ll b,ll m=MOD){ll r=1;while(b>0){if(b&1)r=r*a%m;a=a*a%m;b>>=1;}return r;}
ll power(ll a,ll b){ll r=1;while(b>0){if(b&1)r=r*a;a=a*a;b>>=1;}return r;}
ll gcd(ll a,ll b){if(!b)return a;return gcd(b,a%b);}
ll inv(ll a, ll m = MOD){return powmod(a,m-2,m);}
ll lcm(ll a,ll b){return(a*b)/gcd(a,b);}

//ordered_set X;
//X.insert(3);
//X.order_of_key(3) no of elements less than 3
//*X.find_by_order(n) nth greatest element(0-indexed) 
bitset <N> g[N];
vector <bool> bin[16];
int n, pre[N][N] = {}, ans;

int main(){
	FIO;
	for(int i = 1; i <= 16; ++i){
		int x = i;
		while(x > 0){
			bin[i].push_back(x % 2);
			x /= 2;
		}
		while(bin[i].size() < 4) bin[i].push_back(0);
		reverse(bin[i].begin(), bin[i].end());
	}
	cin >> n;
	for(int i = 1; i <= n; ++i){
		string s;
		cin >> s;
		s = '@' + s;
		int jj = 1;
		for(int j = 1; j <= (int)s.size(); ++j){
			if('1' <= s[j] && s[j] <= '9'){
				for(auto x : bin[s[j] - '0']){
					g[i][jj] = x;
					++jj;
				}
			}
			else{
				for(auto x : bin[s[j] - 'A' + 10]){
					g[i][jj] = x;
					++jj;
				}
			}
		}
	}
	pre[0][0] = 0;
	for(int i = 1; i <= n; ++i){
		pre[0][i] = pre[i][0] = 0;
	}
	for(int i = 1; i <= n; ++i){
		for(int j = 1; j <= n; ++j){
			if(j > 1)
				pre[i][j] += pre[i][j - 1] + (int)g[i][j];
			else
				pre[i][j] = (int)g[i][j];
			//cout << pre[i][j] << " ";
		}
		//cout << "\n";
	}
	//cout << "\n";
	for(int i = 1; i <= n; ++i){
		for(int j = 1; j <= n; ++j){
			if(i > 1)
				pre[i][j] += pre[i - 1][j];
			//cout << pre[i][j] << " ";
		}
		//cout << "\n";
	}

	for(int i = 1; i <= n; ++i){
		bool ok = 1;
		int p, q;
		for(p = i; p <= n; p += i){
			for(q = i; q <= n; q += i){
				if(g[p][q] == 1){
					int cnt = pre[p][q] - pre[p][q - i] - pre[p - i][q] + pre[p - i][q - i];
					if(cnt != i * i){
						ok = 0;
						break;
					}
				}
				else{
					int cnt = pre[p][q] - pre[p][q - i] - pre[p - i][q] + pre[p - i][q - i];
					if(cnt != 0){
						ok = 0;
						break;
					}
				}
			}
		}
		int x = n % i;
		if(x)
		for(int p = i; p <= n; p += i){
			int cnt = pre[p][n] - pre[p][n - x] - pre[p - i][x] + pre[p - i][n - x];
			if(cnt != i * x){
				ok = 0;
				break;
			}
		}
		if(x)
		for(int q = i; q <= n; q += i){
			int cnt = pre[n][q] - pre[n][q - i] - pre[n - x][q] + pre[n - x][q - i];
			if(cnt != i * x){
				ok = 0;
				break;
			}
		}
		int cnt = pre[n][n] - pre[n - x][n] - pre[n][n - x] + pre[n - x][n - x];
		if(x && cnt != i * x){
			ok = 0;
			break;
		}
		if(ok){
			ans = max(ans, i);
		}
	}

	cout << ans;
}
