#include <bits/stdc++.h>

#define debug(s) cout << s << endl
#define debug1(s, t) cout << s << " " << t << endl
#define debug2(s, t, u) cout << s << " " << t << " " << u << endl
#define printvec(v)       \
    for (auto &&i : v)    \
        cout << i << " "; \
    cout << endl

using namespace std;
using i64 = long long;

template <class M> // M: モノイド
struct SegmentTree
{
    vector<M> tree;
    int size;     // ベクトル全体の長さ
    int leaf_len; // 葉（区間）の長さ
    M mempty;
    function<M(M, M)> binary_operation;

    // コンストラクタ nは2の累乗（葉の個数） eは単位元
    SegmentTree(int n, M e, function<M(M, M)> biop)
        : tree(2 * n - 1, e),
          size(2 * n - 1),
          leaf_len(n),
          mempty(e),
          binary_operation(biop)
    {
    }
    // コンストラクタ nは2の累乗（葉の個数）e: 単位元 initval: 初期値
    SegmentTree(int n, M e, function<M(M, M)> biop, M initval)
        : tree(2 * n - 1, initval),
          size(2 * n - 1),
          leaf_len(n),
          mempty(e),
          binary_operation(biop)
    {
    }
    // コンストラクタ nは2の累乗（葉の個数）e: 単位元 initvec: 初期値のベクトル
    SegmentTree(int n, M e, function<M(M, M)> biop, vector<M> initvec)
        : tree(2 * n - 1, e),
          size(2 * n - 1),
          leaf_len(n),
          mempty(e),
          binary_operation(biop)
    {
        for (int k = n - 1; k <= 2 * n - 2; k++)
            tree[k] = initvec[k + 1 - n];
        for (int k = n - 2; k >= 0; k--)
            tree[k] = biop(lchild(k), rchild(k));
    }

    // 葉の座標、値を格納
    void set(int i_leaf, int x) { tree[to_tree_ix(i_leaf)] = x; }

    // まとめて更新
    void build()
    {
        for (int k = leaf_len - 2; k >= 0; k--)
            tree[k] = binary_operation(lchild(k), rchild(k));
    }

private:
    // 子、親への参照　左辺値にもなれる
    M &lchild(int ix) { return tree[2 * ix + 1]; }
    M &rchild(int ix) { return tree[2 * ix + 2]; }
    M &par(int ix) { return tree[(ix - 1) / 2]; }

    constexpr int to_tree_ix(int i_leaf) { return i_leaf + leaf_len - 1; }
    constexpr int get_lchild_ix(int ix) { return 2 * ix + 1; }
    constexpr int get_rchild_ix(int ix) { return 2 * ix + 2; }
    constexpr int get_par_ix(int ix) { return (ix - 1) / 2; }

public:
    // 葉の値の更新 (O(log n))
    void update(int ix, M x)
    {
        ix += leaf_len - 1;
        tree[ix] = x;
        set(ix, x);
        while (ix > 0)
        {
            par[ix] = binary_operation(lchild(ix), rchild(ix));
            ix = get_par_ix(ix);
        }
    }

    // 区間中を二項演算で畳み込む
    int fold(int a, int b) { return fold_sub(a, b, 0, 0, leaf_len); }

private:
    M fold_sub(int a, int b, int k, int l, int r)
    {
        // k: 現在見ているノードの位置
        // [l,r): tree[k] が表している区間
        if (r <= a || b <= l)
            return mempty;
        else if (a <= l && r <= b)
            return tree[k];
        else
        {
            M vl = fold_sub(a, b, get_lchild_ix(k), l, (l + r) / 2);
            M vr = fold_sub(a, b, get_rchild_ix(k), (l + r) / 2, r);
            return binary_operation(vl, vr);
        }
    }
};

// m > n >= 0
template <class T>
T gcd(T m, T n)
{
    if (n > m)
        swap(m, n);
    if (n == 0)
        return m;
    return gcd(n, m % n);
}

int main()
{
    int n;
    cin >> n;

    vector<int> a(n);
    for (auto &&i : a)
    {
        cin >> i;
    }

    /* INITIALIZING SEGMENT-TREE */
    auto bo = [](int m, int n) -> int { return gcd(m, n); };
    int mempty = 0;

    int N = 1; // smallest 2-power where N >= n.
    do
    {
        N *= 2;
    } while (N <= n);

    SegmentTree<int> st(N, mempty, bo, a);

    // 区間[0,i-1], [i+1,n]のgcdを求める
    int gcd_sub = 0;
    for (int i = 0; i < n; i++)
    {
        gcd_sub = max(gcd_sub, gcd(st.fold(0, i), st.fold(i + 1, n)));
    }

    cout << gcd_sub << endl;

    return 0;
}

Measured memory_bytes: 2048