#include <iostream>
#include <vector>
using namespace std;

#ifdef DEBUG
    #define IFD if(true)
#else
    #define IFD if(false)
#endif

// セグメント木 //////////////////////////////////

#include <iostream>
#include <sstream>
#include <vector>
#include <limits.h>

template<typename T_st_data>
class SegTree
{
private:
    int cnt;      // 実際の要素数
    int cnt_pow2; // 簡単のためサイズを 2 のべき乗になるように広げておく
    int size;     // 全体の要素数 (2 * cnt_pow2 - 1)
    T_st_data default_value; // デフォルトの値（最小値を求める場合は大きい値というように消えるように）
    std::vector<T_st_data>* data; // データ本体

    T_st_data query_inner(T_st_data a, T_st_data b, int k, int l, int r)
    {
        // [a, b) と [l, r) が交差しなければ処理の過程で消える値を返す
        if(r <= a || b <= l) return default_value;
        if(a <= l && r <= b) {
            return (*data)[k];
        } else {
            T_st_data vl = query_inner(a, b, k * 2 + 1, l, (l + r) / 2);
            T_st_data vr = query_inner(a, b, k * 2 + 2, (l + r) / 2, r);
            return Calc(vl, vr);
        }
    }

    virtual T_st_data Calc(T_st_data a, T_st_data b) = 0;

public:
    SegTree(int n, T_st_data dv)
    {
        default_value = dv;
        cnt = n;
        cnt_pow2 = 1;
        while(cnt_pow2 < cnt) cnt_pow2 *= 2;
        size = 2 * cnt_pow2 - 1;

        // 一番上のノードがインデックス 0、そこからピラミッド状に広がり
        // 一番下のノードがインデックス cnt_pow2 - 1 ～ 2 * cnt_pow2 - 2 までとなる
        data = new std::vector<T_st_data>(size);
        for(int i = 0; i < size; i++) {
            (*data)[i] = default_value;
        }
    }

    virtual ~SegTree() { delete data; }

    T_st_data Get(int k)
    {
        if(k < 0 || k >= cnt) {
            std::ostringstream s;
            s << "k = " << k;
            throw std::out_of_range(s.str());
        }

        // cnt_pow2 - 1 を加算するとインデックス k を保存している一番下のノードが得られる
        k += cnt_pow2 - 1;
        return (*data)[k];
    }

    void Update(int k, T_st_data a)
    {
        if(k < 0 || k >= cnt) {
            std::ostringstream s;
            s << k << " -> " << a;
            throw std::out_of_range(s.str());
        }

        k += cnt_pow2 - 1;
        (*data)[k] = a;

        // ピラミッドを上りながら更新
        while (k > 0) {
            k = (k - 1) / 2;
            (*data)[k] = Calc((*data)[k * 2 + 1], (*data)[k * 2 + 2]);
        }
    }

    // 指定範囲を探索。[a, b) の範囲であることに注意
    T_st_data Query(T_st_data a, T_st_data b)
    {
        return query_inner(a, b, 0, 0, cnt_pow2);
    }

    // 内容を出力して確認
    void Show()
    {
        int c = 2;
        for(int i = 0; i < cnt_pow2 + cnt - 1; i++) {
            if(i == c - 1) {
                std::cout << std::endl;
                c *= 2;
            }
            std::cout << (*data)[i] << " ";
        }
        std::cout << std::endl;
    }
};

// 範囲内の最大公約数を求める（int 型）
class SegTreeGCD: public SegTree<int>
{
private:
    int Calc(int a, int b) { return gcd(a, b); }
public:
    // デフォルト値は 0（gcd 関数は片一方が 0 の場合は他方を返すため）
    SegTreeGCD(int n): SegTree(n, 0) {}
    static int gcd(int a, int b) {
        if(b == 0) return a;
        return gcd(b, a % b);
    }
};
//////////////////////////////////////////////////

int main()
{
    int N, ans;
    cin >> N;

    SegTreeGCD A(N + 1);
    for(int i = 1; i <= N; i++) {
        int a;
        cin >> a;
        A.Update(i, a);
    }

    ans = 0;
    for(int i = 1; i <= N; i++) {
        ans = max(ans, SegTreeGCD::gcd(A.Query(1, i), A.Query(i + 1, N + 1)));
    }

    cout << ans << endl;

    return 0;
}


Measured memory_bytes: 1280