#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <functional>
#include <iomanip>
#include <cstring>
#define vll vector<ll>
#define vvvl vector<vvl>
#define vvl vector<vector<ll>>
#define VV(a, b, c, d) vector<vector<d>>(a, vector<d>(b, c))
#define VVV(a, b, c, d) vector<vvl>(a, vvl(b, vll (c, d)));
#define re(c, b) for(ll c=0;c<b;c++)
#define all(obj) (obj).begin(), (obj).end()
typedef long long int ll;
typedef long double ld;
using namespace std;


template<typename T>
struct PersistentSegtree{
  #define SPLIT 2
  typedef function<T(T, T)> G; //merge
  typedef function<T(T, T)> H; //update
  G g;
  H h;
  T UNIT;
  ll ver = 0, M=1;
  PersistentSegtree(ll N, T unit, G merge_func, H update_func):UNIT(unit){
    g = merge_func;
    h = update_func;
    while(M<N) M*=2;
  }
  struct vertex{
    T dat;
    vertex* par;
    array<vertex*, SPLIT> ch;
    vertex(){ch.fill(nullptr), par = nullptr;};
  };
  vertex* root = nullptr;
  vector<vertex*> version;//指定したバージョンのルート

  inline ll biset(ll v, ll idx, T x){
    vertex* par = (v==-1?root:version[v]);
    ll k = idx;
    vertex* now = new vertex();
    if(par){
      now->ch = par->ch;
      now->dat = par->dat;
      now->par = par->par;
    }

    version.push_back(now);
    vector<ll> path;
    while(k){
      path.push_back(!(k&1));
      k = (k-1)/2;
    }
    reverse(all(path));

    for(auto t:path){
      par = now->ch[t];
      vertex* tmp = new vertex();
      now->ch[t] = tmp;
      tmp->par = now;
      now = tmp;
      if(par){
        now->ch = par->ch;
        now->dat = par->dat;
      }
    }
    now->dat = h(now->dat, x);

    while(now->par){
      now = now->par;
      ll L = (now->ch[0]?now->ch[0]->dat:UNIT);
      ll R = (now->ch[1]?now->ch[1]->dat:UNIT);
      now->dat = g(L, R);
    }

    return ver++;
  }

  inline T search(vertex* now, ll a, ll b=-1, ll k=0, ll l=0, ll r=-1){
    if(now==nullptr) return UNIT;
    if(r<=a || b<=l) return UNIT;
    if(a<=l && r<=b) return now->dat;
    T A = search(now->ch[0], a, b, k*2+1, l, (l+r)/2);
    T B = search(now->ch[1], a, b, k*2+2, (l+r)/2, r);
    return g(A, B);
  }

  inline ll update(ll v, ll k, T x,ll l=0, ll r=-1){
    if(r==-1) r = M;
    k+=M-1;
    return biset(v, k, x);
  }

  inline T query(ll v, ll a, ll b=-1, ll k=0, ll l=0, ll r=-1){
    if(r==-1) r = M;
    if(b==-1) b = M;
    vertex* now = (v==-1?root:version[v]);
    return search(now, a, b, k, l, r);
  }
};

ll gcd(ll a, ll b){
  if(b<a) swap(a, b);
  ll r = a % b;
  if(r==0) return b;
  while(r!=0) r = a % b, a = b, b = r;
  return a;
}

ll mg(ll l, ll r){
  if(l==0) return r;
  if(r==0) return l;
  return gcd(l, r);
}
ll upd(ll old, ll nw){
  return nw;
}


int main(){
  ll n;std::cin >> n;
  PersistentSegtree<ll> seg(n+1, 0, mg, upd);
  ll v = -1;

  for(int i=0;i<n;i++){
    ll t;scanf("%lld", &t);
    v = seg.update(v, i, t);
  }
  
  ll ans = 0;
  for(int i=0;i<n;i++){
    ll L = seg.query(v, 0, i);
    ll R = seg.query(v, i+1, n);
    ans = max(ans, gcd(L, R));
  }
  std::cout << ans << '\n';
}


Measured memory_bytes: 88576