// Original C++ solution (slower):
// #define _GLIBCXX_DEBUG // for STL debug (optional)

#include <iostream>

#include <iomanip>

#include <cstdio>

#include <string>

#include <cstring>

#include <deque>

#include <list>

#include <queue>

#include <stack>

#include <vector>

#include <utility>

#include <algorithm>

#include <map>

#include <set>

#include <complex>

#include <cmath>

#include <limits>

#include <cfloat>

#include <climits>

#include <ctime>

#include <cassert>

#include <numeric>

#include <fstream>

#include <functional>

#include <bitset>

#include <unordered_map>

using namespace std;



#define debug(...) fprintf(stderr, __VA_ARGS__)

#define int long long int

 

template<typename T> void chmax(T &a, T b) {a = max(a, b);}

template<typename T> void chmin(T &a, T b) {a = min(a, b);}

template<typename T> void chadd(T &a, T b) {a = a + b;}

 

typedef pair<int, int> pii;

typedef long long ll;

 

int dx[] = {0, 0, 1, -1};

int dy[] = {1, -1, 0, 0};

const ll INF = 1001001001001001LL;

const ll MOD = 1000000007LL;



// 約数全列挙

vector<ll> OutDivisor(ll n) {

    vector<ll> ret;

    for(ll i=1; i*i<=n; i++) {

        if(n % i == 0) {

            ret.push_back(i);

            if(i*i!=n) ret.push_back(n / i);

        }

    }

    return ret;

}



map<int, int> mp;

signed main() {

    int N; cin >> N;

    vector<int> A(N);

    for(int i=0; i<N; i++) {

        cin >> A[i];

    }



    set<int> cand;

    for(int i=0; i<min(N, 2LL); i++) {

        auto vec = OutDivisor(A[i]);

        for(auto e : vec) cand.insert(e);

    }



    for(int i=0; i<N; i++) {

        for(auto e : cand) {

            if(A[i] % e == 0) mp[e]++;

        }

    }



    int ans = 0;

    for(auto e : mp) {

        if(e.second >= N-1) chmax(ans, e.first);

    }

    cout << ans << endl;

    return 0;

}


// Optimized solution to the same problem (faster):
// #define _GLIBCXX_DEBUG // for STL debug (optional)

#include <iostream>

#include <iomanip>

#include <cstdio>

#include <string>

#include <cstring>

#include <deque>

#include <list>

#include <queue>

#include <stack>

#include <vector>

#include <utility>

#include <algorithm>

#include <map>

#include <set>

#include <complex>

#include <cmath>

#include <limits>

#include <cfloat>

#include <climits>

#include <ctime>

#include <cassert>

#include <numeric>

#include <fstream>

#include <functional>

#include <bitset>

using namespace std;



#define debug(...) fprintf(stderr, __VA_ARGS__)

#define int long long int

 

template<typename T> void chmax(T &a, T b) {a = max(a, b);}

template<typename T> void chmin(T &a, T b) {a = min(a, b);}

template<typename T> void chadd(T &a, T b) {a = a + b;}

 

typedef pair<int, int> pii;

typedef long long ll;

 

int dx[] = {0, 0, 1, -1};

int dy[] = {1, -1, 0, 0};

const ll INF = 1001001001001001LL;

const ll MOD = 1000000007LL;



// 抽象 SegmentTree (0-indexed・一点更新・区間取得)

template <typename MonoidType>

struct SegmentTree {

    using Function = function< MonoidType(MonoidType, MonoidType) >;



    // node, identity element

    int n;

    vector<MonoidType> node;

    MonoidType E0;



    // update / combine function

    Function upd_f, cmb_f;



    void build(int m, vector<MonoidType> v = vector<MonoidType>()) {

        if(v != vector<MonoidType>()) m = v.size();

        n = 1; while(n < m) n *= 2;



        node = vector<MonoidType>(2*n-1, E0);

        if(v != vector<MonoidType>()) {

            for(int i=0; i<m; i++) {

                node[n-1+i] = v[i];

            }

            for(int i=n-2; i>=0; i--) {

                node[i] = cmb_f(node[2*i+1], node[2*i+2]);

            }

        }

    }



    // initialize

    SegmentTree() {}

    SegmentTree(int n_, MonoidType E0_,

                Function upd_f_, Function cmb_f_,

                vector<MonoidType> v = vector<MonoidType>()) :

        E0(E0_), upd_f(upd_f_), cmb_f(cmb_f_) {

        build(n_, v);

    }



    // update k-th element (applied value: x)

    void update(int k, MonoidType x) {

        k += n - 1;

        node[k] = upd_f(node[k], x);

        while(k > 0) {

            k = (k - 1) / 2;

            node[k] = cmb_f(node[2*k+1], node[2*k+2]);

        }

    }



    // range query for [a, b)

    // 非再帰のアイデア: http://d.hatena.ne.jp/komiyam/20131202/1385992406

    MonoidType query(int a, int b) {

        MonoidType vl = E0, vr = E0;

        for(int l=a+n, r=b+n; l<r; l>>=1, r>>=1) {

            if(l & 1) vl = cmb_f(vl, node[(l++)-1]);

            if(r & 1) vr = cmb_f(node[(--r)-1], vr);

        }

        return cmb_f(vl, vr);

    }

};



int gcd(int a, int b) {

    return b == 0 ? a : gcd(b, a%b);

}



signed main() {

    int N; cin >> N;

    vector<int> A(N);

    for(int i=0; i<N; i++) {

        cin >> A[i];

    }

    SegmentTree<int> seg(N, 0,

                         [&](int a, int b) { return b; },

                         [&](int a, int b) { return gcd(a, b); },

                         A);



    int ans = 0;

    for(int i=0; i<N; i++) {

        int vl = seg.query(0, i);

        int vr = seg.query(i+1, N);

        ans = max(ans, gcd(vl, vr));

    }

    cout << ans << endl;

    return 0;

}


// Fastest known solution for this problem: