package main
import (
"bufio"
"io"
"math/rand"
"os"
"sort"
"strconv"
"time"
)
type FastInput struct {
data []byte
idx int
}
func (in *FastInput) nextUint64() uint64 {
n := len(in.data)
for in.idx < n {
c := in.data[in.idx]
if c >= '0' && c <= '9' {
break
}
in.idx++
}
var x uint64
for in.idx < n {
c := in.data[in.idx]
if c < '0' || c > '9' {
break
}
x = x*10 + uint64(c-'0')
in.idx++
}
return x
}
func gcd(a, b uint64) uint64 {
for b != 0 {
a, b = b, a%b
}
return a
}
func sieve(limit int) []int {
isComp := make([]bool, limit+1)
primes := make([]int, 0, 80000)
for i := 2; i <= limit; i++ {
if !isComp[i] {
primes = append(primes, i)
if i <= limit/i {
for j := i * i; j <= limit; j += i {
isComp[j] = true
}
}
}
}
return primes
}
func factorize(x uint64, primes []int) ([]uint64, []int) {
ps := make([]uint64, 0, 12)
es := make([]int, 0, 12)
for _, p := range primes {
pp := uint64(p)
if pp*pp > x {
break
}
if x%pp == 0 {
c := 0
for x%pp == 0 {
x /= pp
c++
}
ps = append(ps, pp)
es = append(es, c)
}
}
if x > 1 {
ps = append(ps, x)
es = append(es, 1)
}
return ps, es
}
func buildDivisors(ps []uint64, es []int) ([]uint64, map[uint64]int, []int) {
m := len(ps)
stride := make([]int, m)
d := 1
for i := 0; i < m; i++ {
stride[i] = d
d *= es[i] + 1
}
values := make([]uint64, d)
idxMap := make(map[uint64]int, d)
var dfs func(int, uint64, int)
dfs = func(pos int, cur uint64, idx int) {
if pos == m {
values[idx] = cur
idxMap[cur] = idx
return
}
mul := uint64(1)
step := stride[pos]
for e := 0; e <= es[pos]; e++ {
dfs(pos+1, cur*mul, idx+e*step)
if e < es[pos] {
mul *= ps[pos]
}
}
}
dfs(0, 1, 0)
return values, idxMap, stride
}
func processSample(x uint64, a []uint64, need int, primes []int, best *uint64) {
ps, es := factorize(x, primes)
values, idxMap, stride := buildDivisors(ps, es)
cnt := make([]int, len(values))
for _, v := range a {
cnt[idxMap[gcd(v, x)]]++
}
if cnt[idxMap[x]] >= need {
if x > *best {
*best = x
}
return
}
for j := 0; j < len(ps); j++ {
step := stride[j]
block := step * (es[j] + 1)
for base := 0; base < len(values); base += block {
for off := 0; off < step; off++ {
start := base + off
for e := es[j] - 1; e >= 0; e-- {
cnt[start+e*step] += cnt[start+(e+1)*step]
}
}
}
}
b := *best
for i, v := range values {
if v > b && cnt[i] >= need {
b = v
}
}
*best = b
}
func printAns(ans uint64) {
w := bufio.NewWriterSize(os.Stdout, 32)
w.WriteString(strconv.FormatUint(ans, 10))
w.WriteByte('\n')
w.Flush()
}
func main() {
data, _ := io.ReadAll(bufio.NewReaderSize(os.Stdin, 1<<20))
in := FastInput{data: data}
n := int(in.nextUint64())
a := make([]uint64, n)
var maxVal uint64
var first uint64
same := true
for i := 0; i < n; i++ {
v := in.nextUint64()
a[i] = v
if v > maxVal {
maxVal = v
}
if i == 0 {
first = v
} else if v != first {
same = false
}
}
if n <= 2 || same {
printAns(maxVal)
return
}
need := (n + 1) / 2
raw := make([]uint64, 0, 64)
raw = append(raw, a[0], a[n/3], a[n/2], a[2*n/3], a[n-1], maxVal)
if n <= 500 {
raw = append(raw, a...)
} else {
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < 28; i++ {
raw = append(raw, a[rng.Intn(n)])
}
}
seen := make(map[uint64]struct{}, len(raw))
samples := make([]uint64, 0, len(raw))
for _, v := range raw {
if _, ok := seen[v]; !ok {
seen[v] = struct{}{}
samples = append(samples, v)
}
}
sort.Slice(samples, func(i, j int) bool { return samples[i] > samples[j] })
primes := sieve(1000000)
best := uint64(1)
for _, x := range samples {
if x <= best {
break
}
processSample(x, a, need, primes, &best)
if best == maxVal {
break
}
}
printAns(best)
}