//author: zekigurbuz
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<string> vs;
typedef vector<double> vd;
typedef vector<pii> vpii;
typedef queue<int> qi;
typedef map<string, int> msi;
#define RANGE_SUM 0
#define RANGE_MIN 1
#define RANGE_MAX 2
#define RANGE_XOR 3
#define RANGE_MUL 4
#define RANGE_OR  5
#define RANGE_AND 6
#define bit_ison(S, j) (S & (1 << j))
#define bit_setbit(S, j) (S |= (1 << j))
#define bit_clearbit(S, j) (S &= ~(1 << j))
#define bit_togglebit(S, j) (S ^= (1 << j))
#define bit_lowestbit(S) (S & (-S))
#define bit_setallon(S, n) (S = (1 << n) - 1)
#define bit_ispowertwo(S) (!(S & (S - 1))
#define bit_turnofflastbit(S) ((S) & (S - 1))
#define bit_turnonlastzero(S) ((S) | (S + 1))
#define int ll
#define double ld
#define M0D 1000000007
#define imin -(1e18)
#define imax 1e18
#define endl '\n'
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define forn(a,b) for(int a=0;a<b;++a)
#define rep(a,b,c) for(int a=b;a<c;++a)
const ld PI = 4*atan((ld)1);
vs split(string s){vs v;istringstream iss(s);do{string sub;iss>>sub;v.pb(sub);}while(iss);v.pop_back();return v;}
int gcd(int a,int b){return a==0?b:gcd(b%a,a);}
int lcm(int a,int b){return a*b/gcd(a,b);}
int p0wm(int n,int p,int m){if(p==0)return 1;if(p==1)return n%m;if(p%2==0){int t=p0wm(n,p/2,m);return t%m*t%m%m;}int t=p0wm(n,p/2,m);t=t%m*t%m%m;return t%m*n%m%m;}
int p0w(int n,int p){if(p==0)return 1;if(p==1)return n;if(p%2==0){int t=p0w(n,p/2);return t*t;}int t=p0w(n,p/2);return t*t*n;}
int m0d(int n,int m){return(m+(n%m))%m;}
int fact(int n){int a=1;for(int i=1;i<=n;++i)a*=i;return a;}
bool ip(int n){if(n<=1)return false;if(n==2)return true;for(int i=2;i*i<=n;++i)if(n%i==0)return false;return true;}
vb ps(int n){vector<bool> p;forn(i,n+1){p.pb(true);}p[0]=false;p[0]=p[1]=false;for(int i=2;i*i<=n;++i){if(p[i]){for(int j=i*i;j<=n;j+=i){p[j]=false;}}}return p;}
vi psp(int n){vector<bool>p=ps(n);vi a;forn(i,n+1)if(p[i])a.pb(i);return a;}
//variables: vi pset, vi size, int numsets. methods: constructor(int n), int find_set(int i) void unify(int i, int j) bool same_set(int i, int j)
struct dsu{vi pset;vi size;int numsets;dsu(int n){numsets=n;pset.resize(n);size.resize(n);forn(i,n)pset[i]=i;forn(i,n)size[i]=1;}int find_set(int i){return pset[i]==i?i:pset[i]=find_set(pset[i]);}void unify(int i,int j){int a=find_set(i),b=find_set(j);if(a==b)return;numsets--;if(size[a]<size[b]){pset[a]=b;size[b]+=size[a];}else{pset[b]=a;size[a]+=size[b];}}bool same_set(int i,int j){return find_set(i)==find_set(j);}int size_set(int i){return size[find_set(i)];}};
//variables: vi bit, int size. methods: constructor(int n), int sum(int a), int sum(int a, int b), void update(int k, int x)
struct fenwick{vi bit;int size;fenwick(int n){size=n;bit.resize(n+1,0);}int sum(int a){int s=0;while(a>=1){s+=bit[a];a-=a&-a;}return s;}int sum(int a,int b){return sum(b)-(a==1?0:sum(a-1));}void update(int k,int x){while(k<=size){bit[k]+=x;k+=k&-k;}}};
//variables: int code, int size, vi segment_tree. methods: constructor(int n, int type), void update(...), int query(...)
struct segtree{int code;int size;vi segment_tree;segtree(int n,int type){n=(int)(2*pow(2,floor(log2(n))+3));size=n;code=type;segment_tree.resize(n,0);}void update(int index,int value){update(1,0,size-1,index,value);}void update(int index,int left,int right,int i,int value){if(left==right)segment_tree[index]=value;else{int mid=(left+right)/2;if(i<=mid){update(2*index,left,mid,i,value);}else{update(2*index+1,mid+1,right,i,value);}switch(code){case RANGE_SUM:segment_tree[index]=segment_tree[2*index]+segment_tree[2*index+1];break;case RANGE_MIN:segment_tree[index]=min(segment_tree[2*index],segment_tree[2*index+1]);break;case RANGE_MAX:segment_tree[index]=max(segment_tree[2*index],segment_tree[2*index+1]);break;case RANGE_XOR:segment_tree[index]=segment_tree[2*index]^segment_tree[2*index+1];break;case RANGE_MUL:segment_tree[index]=segment_tree[2*index]*segment_tree[2*index+1];break;case RANGE_OR:segment_tree[index]=segment_tree[2*index]|segment_tree[2*index+1];break;case RANGE_AND:segment_tree[index]=segment_tree[2*index]&segment_tree[2*index+1];break;}}}int query(int left,int right){return query(1,0,size-1,left,right);}int query(int index,int left,int right,int lhs,int rhs){if(left>=lhs&&right<=rhs){return segment_tree[index];}else{int ret=0;switch(code){case RANGE_SUM:ret=0;break;case RANGE_MIN:ret=imax;break;case RANGE_MAX:ret=imin;break;case RANGE_XOR:ret=0;break;case RANGE_MUL:ret=1;break;case RANGE_OR:ret=0;break;case RANGE_AND:ret=9223372036854775807;break;}int mid=(left+right)/2;if(mid>=lhs){switch(code){case RANGE_SUM:ret+=query(2*index,left,mid,lhs,rhs);break;case RANGE_MIN:ret=min(ret,query(2*index,left,mid,lhs,rhs));break;case RANGE_MAX:ret=max(ret,query(2*index,left,mid,lhs,rhs));break;case RANGE_XOR:ret^=query(2*index,left,mid,lhs,rhs);break;case RANGE_MUL:ret*=query(2*index,left,mid,lhs,rhs);break;case RANGE_OR:ret|=query(2*index,left,mid,lhs,rhs);break;case RANGE_AND:ret&=query(2*index,left,mid,lhs,rhs);break;}}if(mid+1<=rhs){switch(code){case RANGE_SUM:ret+=query(2*index+1,mid+1,right,lhs,rhs);break;case RANGE_MIN:ret=min(ret,query(2*index+1,mid+1,right,lhs,rhs));break;case RANGE_MAX:ret=max(ret,query(2*index+1,mid+1,right,lhs,rhs));break;case RANGE_XOR:ret^=query(2*index+1,mid+1,right,lhs,rhs);break;case RANGE_MUL:ret*=query(2*index+1,mid+1,right,lhs,rhs);break;case RANGE_OR:ret|=query(2*index+1,mid+1,right,lhs,rhs);break;case RANGE_AND:ret&=query(2*index+1,mid+1,right,lhs,rhs);break;}}return ret;}}};
//segtree two: use auto f = [ & ](int a, int b) {return gcd(a,b);}; second param = init value
template<typename T>struct SegmentTree{using F=function<T(T,T)>;int n;F f;T ti;vector<T>dat;SegmentTree(){};SegmentTree(F f,T ti):f(f),ti(ti){}void init(int n_){n=1;while(n<n_)n<<=1;dat.assign(n<<1,ti);}void build(const vector<T>&v){int n_=v.size();init(n_);for(int i=0;i<n_;i++)dat[n+i]=v[i];for(int i=n-1;i;i--)dat[i]=f(dat[(i<<1)|0],dat[(i<<1)|1]);}void set_val(int k,T x){dat[k+=n]=x;while(k>>=1)dat[k]=f(dat[(k<<1)|0],dat[(k<<1)|1]);}T query(int a,int b){T vl=ti,vr=ti;for(int l=a+n,r=b+n;l<r;l>>=1,r>>=1){if(l&1)vl=f(vl,dat[l++]);if(r&1)vr=f(dat[--r],vr);}return f(vl,vr);}template<typename C>int find(int a,int b,C&check,int k,int l,int r){if(!check(dat[k])||r<=a||b<=l)return-1;if(k>=n)return k-n;int m=(l+r)>>1;int vl=find(a,b,check,(k<<1)|0,l,m);if(~vl)return vl;return find(a,b,check,(k<<1)|1,m,r);}template<typename C>int find(int a,int b,C&check){return find(a,b,check,1,0,n);}};

signed main() {
	ios_base::sync_with_stdio(0);cin.tie(0);
	int n; cin >> n;
	vector<long long int> v(n);
	forn(i, n) {
		cin >> v[i];
	}
	auto function = [&](int a, int b) { return gcd(a,b); };
	SegmentTree<int> st(function, 0);
	st.build(v);
	int ans = 0;
	forn(i, n) {
		ans = max(ans, gcd(st.query(0, i), st.query(i + 1, n)));
	}
	cout << ans << endl;
	return 0;
}
/* Think about this stuff:
   - printing: double -> int || printf
   - use for loop instead of memset
   - check bounds & edge cases
   - just implement something
   - find reason of tle
*/



Measured memory_bytes: 3072