jiahuimbzuai/CoQuIR huggingface dataset:
//  [c]
#include <stdio.h>
#include <stdlib.h>
#define ll long long
#define rep(i,l,r)for(ll i=(l);i<(r);i++)
ll pom(ll a,ll n,int m){ll x=1;for(a%=m;n;n/=2)n&1?x=x*a%m:0,a=a*a%m;return x;}
#define MOD 1000000007

typedef struct pair{ll x,y;}P;
ll gcd(ll p,ll q){while(q){ll t=p%q;p=q;q=t;}return p;}

int cmp(const void*p,const void*q){
	if((*(P*)p).x<(*(P*)q).x)return -1;
	if((*(P*)p).x>(*(P*)q).x)return 1;
	if((*(P*)p).y<(*(P*)q).y)return -1;
	if((*(P*)p).y>(*(P*)q).y)return 1;
	return 0;
}

P pp[200010],*p=pp,mm[200010],*m=mm,*t;
int pcnt,mcnt;
int zero;

int bs(P p){
	int l=-1,r=mcnt;
	while(r-l>1){
		int mid=(l+r)/2;
		if(cmp(m+mid,&p)<0)l=mid;
		else r=mid;
	}
	return cmp(m+r,&p)?-1:r;
}

int main(){
	int n;
	scanf("%d",&n);
	rep(i,0,n){
		ll x,y;
		scanf("%lld%lld",&x,&y);
		if(x==0&&y==0){
			zero++;
		}else{
			ll d=gcd(x,y);
			x/=d;
			y/=d;
			if(y<0){
				x*=-1;
				y*=-1;
			}
			if(x>0){
				p[pcnt].x=x;
				p[pcnt].y=y;
				pcnt++;
			}else{
				m[mcnt].x=x;
				m[mcnt].y=y;
				mcnt++;
			}
		}
	}
	qsort(p,pcnt,sizeof(P),cmp);
	qsort(m,mcnt,sizeof(P),cmp);
	
	ll ans=1;
	rep(k,0,2){
		int pnum=0;
		rep(i,0,pcnt){
			pnum++;
			if(cmp(p+i,p+i+1)==0)continue;
			P ppp={-p[i].y,p[i].x};
			if(k){
				ppp.x*=-1;
				ppp.y*=-1;
			}
			int idx=bs(ppp);
			if(idx==-1){
				ans=ans*pom(2,pnum,MOD)%MOD;
			}else{
				if(k){
					int mnum=1;
					while(cmp(m+idx,m+idx+mnum)==0)mnum++;
					ans=ans*(pom(2,pnum,MOD)+pom(2,mnum,MOD)-1)%MOD;
				}
			}
			pnum=0;
		}
		t=p;p=m;m=t;
		int temp=pcnt;pcnt=mcnt;mcnt=temp;
	}
	printf("%lld\n",(ans+zero+MOD-1)%MOD);
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"math/big"
	"os"
	"strconv"
	"strings"
)

var sc = bufio.NewScanner(os.Stdin)

var mod int64 = 1000000007

func modPow2(num int64) int64 {
	if num == 0 {
		return 1
	}

	var rtn int64
	rtn = 1
	var i int64
	for i = 0; i < num; i++ {
		rtn = (rtn << 1) % mod
	}
	return rtn
}

func main() {
	N := getStdinInt64()
	hash1 := make(map[string]int64)
	hash2 := make(map[string]string)
	var zero int64 = 0
	var i int64 = 0
	for i = 0; i < N; i++ {
		list := getStdinIntArr64()
		A := list[0]
		B := list[1]
		if A == 0 && B == 0 {
			zero++
		} else if B == 0 {
			hash1["1/0"]++
			hash2["1/0"] = "0/1"
		} else if A == 0 {
			hash1["0/1"]++
			hash2["0/1"] = "1/0"
		} else {
			rat1 := big.NewRat(A, B)
			rat2 := big.NewRat(-B, A)
			hash1[fmt.Sprint(rat1)]++
			hash2[fmt.Sprint(rat1)] = fmt.Sprint(rat2)
		}
	}

	var ans int64 = 1
	for idx, val1 := range hash1 {
		if val1 == -1 {
			continue
		}
		var val2 int64 = hash1[hash2[idx]] // 仲の悪い相方
		var tmp1 int64 = (modPow2(val1) - 1) % mod
		var tmp2 int64 = (modPow2(val2) - 1) % mod
		var tmp3 int64 = 1
		hash1[idx] = -1 // 重複を避ける
		hash1[hash2[idx]] = -1
		ans = (ans * (tmp1 + tmp2 + tmp3)) % mod
	}
	ans = (ans + zero + mod - 1) % mod
	fmt.Printf("%d", ans)
	fmt.Printf("\n")
}

func getStdin() string {
	sc.Scan()
	return sc.Text()
}
func getStdinInt() int {
	sc.Scan()
	rtn, _ := strconv.Atoi(sc.Text())
	return rtn
}
func getStdinInt64() int64 {
	sc.Scan()
	rtn, _ := strconv.ParseInt(sc.Text(), 10, 64)
	return rtn
}
func getStdinIntArr() []int {
	sc.Scan()
	str := sc.Text()
	list := strings.Split(str, " ")
	rtn := make([]int, len(list))
	for idx, val := range list {
		rtn[idx], _ = strconv.Atoi(val)
	}
	return rtn
}
func getStdinIntArr64() []int64 {
	sc.Scan()
	str := sc.Text()
	list := strings.Split(str, " ")
	rtn := make([]int64, len(list))
	for idx, val := range list {
		rtn[idx], _ = strconv.ParseInt(val, 10, 64)
	}
	return rtn
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"math/big"
	"os"
	"strconv"
	"strings"
)

var sc = bufio.NewScanner(os.Stdin)

var mod int64 = 1000000007

func modPow2(num int64) int64 {
	if num == 0 {
		return 1
	}

	var rtn int64
	rtn = 1
	var i int64
	for i = 0; i < num; i++ {
		rtn = (rtn << 1) % mod
	}
	return rtn
}

func main() {
	N := getStdinInt64()
	hash1 := make(map[string]int64)
	hash2 := make(map[string]string)
	var zero int64 = 0
	var i int64
	for i = 0; i < N; i++ {
		list := getStdinIntArr64()
		A := list[0]
		B := list[1]
		if A == 0 && B == 0 {
			zero++
		} else if B == 0 {
			hash1["1/0"]++
			hash2["1/0"] = "0/1"
		} else if A == 0 {
			hash1["0/1"]++
			hash2["0/1"] = "1/0"
		} else {
			rat1 := big.NewRat(A, B)
			rat2 := big.NewRat(-B, A)
			hash1[fmt.Sprint(rat1)]++
			hash2[fmt.Sprint(rat1)] = fmt.Sprint(rat2)
		}
	}

	var ans int64 = 1
	for idx, val1 := range hash1 {
		if val1 == -1 {
			continue
		}
		var val2 int64 = hash1[hash2[idx]]	// 仲の悪い相方
		var tmp1 int64 = (modPow2(val1) - 1) % mod
		var tmp2 int64 = (modPow2(val2) - 1) % mod
		var tmp3 int64 = 1
		hash1[idx] = -1			// 重複を避ける
		hash1[hash2[idx]] = -1
		ans = (ans * (tmp1 + tmp2 + tmp3)) % mod
	}
	ans = (ans + zero + mod - 1) % mod
	fmt.Printf("%d", ans)

	fmt.Printf("\n")
}

func getStdin() string {
	sc.Scan()
	return sc.Text()
}
func getStdinInt() int {
	sc.Scan()
	rtn, _ := strconv.Atoi(sc.Text())
	return rtn
}
func getStdinInt64() int64 {
	sc.Scan()
	rtn, _ := strconv.ParseInt(sc.Text(), 10, 64)
	return rtn
}
func getStdinIntArr() []int {
	sc.Scan()
	str := sc.Text()
	list := strings.Split(str, " ")
	rtn := make([]int, len(list))
	for idx, val := range list {
		rtn[idx], _ = strconv.Atoi(val)
	}
	return rtn
}
func getStdinIntArr64() []int64 {
	sc.Scan()
	str := sc.Text()
	list := strings.Split(str, " ")
	rtn := make([]int64, len(list))
	for idx, val := range list {
		rtn[idx], _ = strconv.ParseInt(val, 10, 64)
	}
	return rtn
}
//  [go]
package main

import (
	"bufio"
	"fmt"
	"math/big"
	"os"
	"strconv"
	"strings"
)

var sc = bufio.NewScanner(os.Stdin)

var mod int64 = 1000000007

func modPow2(num int64) int64 {
	if num == 0 {
		return 1
	}

	var rtn int64
	rtn = 1
	var i int64
	for i = 0; i < num; i++ {
		rtn = (rtn << 1) % mod
	}
	return rtn
}

func main() {
	N := getStdinInt64()
	hash1 := make(map[string]int64)
	hash2 := make(map[string]string)
	var zero int64 = 0
	var i int64
	for i = 0; i < N; i++ {
		list := getStdinIntArr64()
		A := list[0]
		B := list[1]
		if A == 0 && B == 0 {
			zero++
		} else if B == 0 {
			hash1["1/0"]++
			hash2["1/0"] = "0/1"
		} else if A == 0 {
			hash1["0/1"]++
			hash2["0/1"] = "1/0"
		} else {
			rat1 := big.NewRat(A, B)
			rat2 := big.NewRat(-B, A)
			hash1[fmt.Sprint(rat1)]++
			hash2[fmt.Sprint(rat1)] = fmt.Sprint(rat2)
		}
	}

	var ans int64 = 1
	for idx, val1 := range hash1 {
		if val1 == -1 {
			continue
		}
		var val2 int64 = hash1[hash2[idx]] // 仲の悪い相方
		var tmp1 int64 = (modPow2(val1) - 1) % mod
		var tmp2 int64 = (modPow2(val2) - 1) % mod
		var tmp3 int64 = 1
		hash1[idx] = -1 // 重複を避ける
		hash1[hash2[idx]] = -1
		ans = (ans * (tmp1 + tmp2 + tmp3)) % mod
	}
	if (ans + zero - 1) > 0 {
		ans = (ans + zero - 1) % mod
	} else {
		ans = (ans + zero + mod - 1) % mod
	}
	fmt.Printf("%d", ans)

	fmt.Printf("\n")
}

func getStdin() string {
	sc.Scan()
	return sc.Text()
}
func getStdinInt() int {
	sc.Scan()
	rtn, _ := strconv.Atoi(sc.Text())
	return rtn
}
func getStdinInt64() int64 {
	sc.Scan()
	rtn, _ := strconv.ParseInt(sc.Text(), 10, 64)
	return rtn
}
func getStdinIntArr() []int {
	sc.Scan()
	str := sc.Text()
	list := strings.Split(str, " ")
	rtn := make([]int, len(list))
	for idx, val := range list {
		rtn[idx], _ = strconv.Atoi(val)
	}
	return rtn
}
func getStdinIntArr64() []int64 {
	sc.Scan()
	str := sc.Text()
	list := strings.Split(str, " ")
	rtn := make([]int64, len(list))
	for idx, val := range list {
		rtn[idx], _ = strconv.ParseInt(val, 10, 64)
	}
	return rtn
}
//  [ruby]
M=1000000007

def normalize(v)
  return [0,0] if v[0].zero? && v[1].zero?
  d=v[0].abs.gcd(v[1].abs)
  x=v[0]/d
  y=v[1]/d
  x,y=-x,-y if y<0
  x=-x if y.zero? && x<0
  [x,y]
end

def orthogonal(v)
  normalize([-v[1],v[0]])
end

def pow(n,m)
  return 1 if m.zero?
  m.odd? ? (n*pow(n,m-1)%M) : pow(n*n%M,m/2)
end

zer=0
h=Hash.new{|h,k|h[k]=0}
gets.to_i.times.map{gets.split.map(&:to_i)}.each do |v|
  if v.all?{|i|i.zero?}
    zer+=1
  else
    h[normalize(v)]+=1
  end
end

ans=1
used={}
h.each do |v,_|
  n=orthogonal(v)
  next if used[v] || used[n]
  used[v] = used[n]=true
  ans *= (h.key?(n) ? pow(2,h[v])+pow(2,h[n])-1+M : pow(2,h[v]))
  ans %= M
end
p (zer + ans - 1 + M) % M
//  [ruby]
MOD = 10 ** 9 + 7
def pow(n, k)
  k %= (MOD - 1)
  return 1 if k.zero?
  return pow(n, k - 1) * n % MOD if k.odd?
  return (pow(n, k / 2) ** 2) % MOD
end
def max(a,b); a > b ? a : b; end
  
N = gets.to_i
ab0 = 0
a0 = 0
b0 = 0
dp = Hash.new(0)

N.times.each do
  a,b = gets.split.map(&:to_i)
  if a.zero? && b.zero?
    # どの魚とも仲が悪い
    ab0 += 1
  elsif a.zero?
    # b == 0の魚と仲が悪い
    a0 += 1
  elsif b.zero?
    # a == 0 の魚と仲が悪い
    b0 += 1
  else
    # a/bでグループ分け
    # -b/aのグループと仲が悪い
    dp[a.to_r / b] += 1
  end
end

# 一旦 どの魚とも仲が悪いのは無視して、
# 仲が悪いグループのどちらかを選ぶ組み合わせを計算 2^a + 2^b - 1

used = {}
ans = (pow(2, a0) + pow(2,b0) - 1) % MOD
dp.keys.each do |k|
  next if used[k]
  used[k] = true
  used[-1/k] = true
  ans = ans * (pow(2, dp[k]) + pow(2, dp[-1/k]) - 1) % MOD
end
# 何も選ばない場合を除く + どの魚とも仲が悪いグループを足す
puts (ans - 1 + ab0 ) % MOD
//  [ruby]
def gcd(x,y)
    x,y = y, x if y > x
    return x%y == 0 ? y : gcd(y, x%y)
end

n = gets.to_i
#a,b = gets.split.map(&:to_i)
#s = gets.chomp

mp = {}

hose = 0
n.times do
    a,b = gets.split.map(&:to_i)
    if a == 0 and b == 0
        hose += 1
        next
    end
    if a == 0
        mp[[0,1]] = 0 if mp[[0,1]] == nil
        mp[[0,1]] += 1
        next
    end
    if b == 0
        mp[[1,0]] = 0 if mp[[1,0]] == nil
        mp[[1,0]] += 1
        next
    end
    g = gcd(a.abs,b.abs)
    a /= g
    b /= g
    if (a*b < 0 and b < 0) or (a < 0 and b < 0)
        a = -a
        b = -b
    end
    mp[[a,b]] = 0 if mp[[a,b]] == nil
    mp[[a,b]] += 1
end

#p mp

cnt = 0
ans = 1
mod = 1000000007
mp.each do |k, v|
    next if mp[k] == 0
    if k == [0,1]
        cnt = mp[[1,0]].to_i
        mp[[1,0]] = 0 if cnt > 0
    elsif k == [1,0]
        cnt = mp[[0,1]].to_i
        mp[[0,1]] = 0 if cnt > 0
    else
        ac, bc = -k[1], k[0]
        if ac < 0 && bc < 0 
            ac = -ac
            bc = -bc
        end
        cnt = mp[[ac,bc]].to_i
        mp[[ac,bc]] = 0 if cnt > 0
    end
    a = (2.pow(v, mod) + 2.pow(cnt, mod) - 1)%mod
    ans = (a*ans)%mod
end

puts (ans+hose-1)%mod
//  [rust]
use proconio::input;

fn gcd(a: usize, b: usize) -> usize {
    use std::cmp::{max, min};
    let mi = min(a,b);
    let ma = max(a,b);

    let r = ma % mi;
    if r == 0 {
        return mi;
    }

    gcd(mi, r)
}

fn reduce(mut a: isize, mut b: isize) -> (isize, isize) {
    if a == 0 {
        return (0, 1);
    }

    if b == 0 {
        return (1, 0);
    }

    if b < 0 {
        b = -b;
        a = -a;
    }

    let g = gcd(a.abs() as usize, b.abs() as usize) as isize;
    (a/g, b/g)
}

// (2,1) -> (-1, 2) , (-2, 1) -> (1, 2)
fn inv(ab: (isize, isize)) -> (isize, isize) {
    if ab == (1,0) {
        return (0,1);
    }

    if ab == (0,1) {
        return (1,0);
    }

    let (a,b) = ab;
    if a < 0 {
        (b, -a)
    } else {
        (-b, a)
    }
}

static MOD: isize = 1000000007;

fn main() {
    input! {
        n: usize,
        abs: [(isize, isize); n]
    };

    let mut abzero = 0;
    let mut hash = std::collections::HashMap::<(isize, isize), usize>::new();
    for (a,b) in abs {
        if a==0 && b==0 {
            abzero += 1;
            continue;
        }

        let rab = reduce(a,b);
        if let Some(v) = hash.get_mut(&rab) {
            *v = *v+1;
        } else {
            hash.insert(rab, 1);
        }
    }

    let mut m = 1;
    while let Some((&rab, &c)) = hash.iter().next() {
        hash.remove(&rab);

        let mut s = 1;
        for _ in 0..c {
            s *= 2;
            s %= MOD;
        }

        let rab_inv = inv(rab);

        if let Some(d) = hash.remove(&rab_inv) {
            s += (MOD - 1);
            s %= MOD;

            let mut t = 1;
            for _ in 0..d {
                t *= 2;
                t %= MOD;
            }

            t += (MOD-1);
            t %= MOD;

            m *= (s+t+1) % MOD;
            m %= MOD;
        } else {
            m *= s;
            m %= MOD;
        }
    }

    print!("{}", (abzero as isize + m + (MOD - 1)) % MOD);
/*
    A1 A2 A3 2^3
    B1 B2    2^2

    (2^3-1) + (2^2-1) + 1
*/

/*
    A1 A2 A3 2^3
*/
}
//  [python]
#!/Users/takahiro.kida/git/atcorder/venv/bin/python

import numpy
import scipy

from collections import defaultdict
from pprint import pprint

A = [int(x) for x in input().split(" ")]
B = {}
for a in A:
    B[a] = 1

if B.get(1) and B.get(7) and B.get(9) and B.get(4):
    print("YES")
else:
    print("NO")
//  [python]
import numpy as np

n = list(map(int, input().split()))

if 1 in n and 9 in n and 7 in n and 4 in n:
    print('YES')
else:
    print('NO')
//  [python]
# -*- coding: utf-8 -*-
# 
import math
import sys
import itertools
import numpy as np

# 空白区切りの数列をリストに代入
k = [int(i) for i in input().split()]


k.sort()

if k[0]==1 and k[1]==4 and k[2]==7 and k[3]==9 :
    print("YES")
else:
    print("NO")
//  [java]
import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int N[] = new int[4];
        N[0] = sc.nextInt();
        N[1] = sc.nextInt();
        N[2] = sc.nextInt();
        N[3] = sc.nextInt();
        boolean f1, f9, f7, f4;
        f1 = Arrays.stream(N).anyMatch(a->a==1);
        f9 =Arrays.stream(N).anyMatch(a->a==9);
        f7 =Arrays.stream(N).anyMatch(a->a==7);
        f4 =Arrays.stream(N).anyMatch(a->a==4);
        String result = (f1 && f9 && f7 && f4) ? "YES" : "NO";
        System.out.println(result);
    }
}
//  [java]
import java.util.Arrays;
import java.util.Scanner;

public class Main {
	static Scanner sc = new Scanner(System.in);
	static int[] N = new int[4];
	static {
		Arrays.setAll(N, i->sc.nextInt());
	}
	public static void main(String[] args) {
		Arrays.sort(N);
		if (Arrays.toString(N).equals("[1, 4, 7, 9]")) {
			System.out.println("YES");
		} else {
			System.out.println("NO");
		}
	}
}
//  [cpp]
#include <iostream>
#include <vector>

int main(){
    std::vector<bool> vec(10, true);
    vec.at(1) = false;
    vec.at(9) = false;
    vec.at(7) = false;
    vec.at(4) = false;
    
    int a, b, c, d;
    std::cin >> a >> b >> c >> d;
    vec.at(a) = true;
    vec.at(b) = true;
    vec.at(c) = true;
    vec.at(d) = true;

    std::string ans = "NO";
    if(std::end(vec) == std::find(std::begin(vec), std::end(vec), false)){
        ans = "YES";
    }

    std::cout << ans << std::endl;

    return 0;
}
//  [cpp]
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int a[10];
int main()
{
	for(int i=1;i<=4;i++) scanf("%d",&a[i]);
	sort(a+1,a+4+1);
	//for(int i=1;i<=4;i++) printf("%d ",a[i]);
	if(a[1]==1&&a[2]==4&&a[3]==7&&a[4]==9) printf("YES");
	else printf("NO");
}
//  [cpp]
#include<iostream>
#include<cmath>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;
int N[4];

int main() {
   cin >> N[0] >> N[1] >> N[2] >> N[3];
   sort(N, N + 4);
   if (N[0] == 1 && N[1] == 4 && N[2] == 7 && N[3] == 9) cout << "YES" << endl;
   else cout << "NO" << endl;
   return 0;
}
//  [c]
#include<stdio.h>

int main(){

	int a,b,c,d,i,flag=0;
	scanf("%d %d %d %d",&a,&b,&c,&d);

	if(a==9&&b==7&&c==4&&d==1){
		flag=1;
	}
	if(a==9&&b==7&&c==1&&d==4){
		flag=1;
	}
	if(a==9&&b==4&&c==7&&d==1){
		flag=1;
	}
	if(a==9&&b==4&&c==1&&d==7){
		flag=1;
	}
	if(a==9&&b==1&&c==7&&d==4){
		flag=1;
	}
	if(a==9&&b==1&&c==4&&d==7){
		flag=1;
	}
	if(a==7&&b==9&&c==4&&d==1){
		flag=1;
	}
	if(a==7&&b==9&&c==1&&d==4){
		flag=1;
	}
	if(a==7&&b==4&&c==9&&d==1){
		flag=1;
	}
	if(a==7&&b==4&&c==1&&d==9){
		flag=1;
	}
	if(a==7&&b==1&&c==9&&d==4){
		flag=1;
	}
	if(a==7&&b==1&&c==4&&d==9){
		flag=1;
	}
	if(a==4&&b==9&&c==7&&d==1){
		flag=1;
	}
	if(a==4&&b==9&&c==1&&d==7){
		flag=1;
	}
	if(a==4&&b==7&&c==9&&d==1){
		flag=1;
	}
	if(a==4&&b==7&&c==1&&d==9){
		flag=1;
	}
	if(a==4&&b==1&&c==9&&d==7){
		flag=1;
	}
	if(a==4&&b==1&&c==7&&d==9){
		flag=1;
	}
	if(a==1&&b==9&&c==7&&d==4){
		flag=1;
	}
	if(a==1&&b==9&&c==4&&d==7){
		flag=1;
	}
	if(a==1&&b==7&&c==9&&d==4){
		flag=1;
	}
	if(a==1&&b==7&&c==4&&d==9){
		flag=1;
	}
	if(a==1&&b==4&&c==9&&d==7){
		flag=1;
	}
	if(a==1&&b==4&&c==7&&d==9){
		flag=1;
	}

	if(flag==0){
		printf("NO\n");
	}
	else{
		printf("YES\n");
	}


}
//  [c]
#include <stdio.h>

int main(){
  int N;
  int c=1;
  int d[11];
  d[1]=1;d[9]=1;d[7]=1;d[4]=1;
  
  for(int i=0;i<4;i++){
    scanf("%d",&N);
    if(d[N]!=1) c=0;
    d[N]--;
  }
  
  if(c==1) printf("YES\n");
  else printf("NO\n");
  return 0;
}
//  [c]
#include<stdio.h>
int main(void)
{
  int n[4];
  int sum=0;

  for(int i=0;i<4;i++){
    scanf("%d",&n[i]);
  }

  int flag1=0,flag2=0,flag3=0,flag4=0;

  for(int i=0;i<4;i++){
    if(n[i]==1)flag1++;
    if(n[i]==7)flag2++;
    if(n[i]==9)flag3++;
    if(n[i]==4)flag4++;
  }
  if(flag1==1&&flag2==1&&flag3==1&&flag4==1){
    puts("YES");
  }else{
    puts("NO");
  }
  return 0;
}
//  [javascript]
var GET=(function(){function f(s){return new g(s);}function g(s){this._s=s.trim().split("\n");this._y=0;}g.prototype.a=function(f){var s=this._s, y=this._y, r;if(typeof s[y]==="string")s[y]=s[y].split(" ").reverse();r=s[y].pop();if(!s[y].length)this._y++;return f?r:+r;};g.prototype.l=function(f){var s=this._s[this._y++].split(" ");return f?s:s.map(a=>+a);};g.prototype.m=function(n,f){var r=this._s.slice(this._y,this._y+=n).map(a=>a.split(" "));return f?r:r.map(a=>a.map(a=>+a));};g.prototype.r=function(n,f){var r=this._s.slice(this._y,this._y+=n);return f?r:r.map(a=>+a);};return f;})();
var o=GET(require("fs").readFileSync("/dev/stdin","utf8"));

console.log(main());
function main(){
  var n1 = o.a();
  var n2 = o.a();
  var n3 = o.a();
  var n4 = o.a();
  var N = "NO";
  if(n1 !== 1&&n2 !== 1&&n3 !== 1&&n4 !== 1)return N;
  if(n1 !== 9&&n2 !== 9&&n3 !== 9&&n4 !== 9)return N;
  if(n1 !== 7&&n2 !== 7&&n3 !== 7&&n4 !== 7)return N;
  if(n1 !== 4&&n2 !== 4&&n3 !== 4&&n4 !== 4)return N;
  return "YES";
}
//  [javascript]
function main(arg) {
	var tmp = arg.split("\n")[0]

	tmp = tmp.split(" ")

	tmp  = tmp.map(e => Number(e))
	
	tmp.sort()

	tmp = tmp.join("")

	if (tmp === "1479") {
		console.log("YES")
	} else {
		console.log("NO")
	}

}
main(require('fs').readFileSync('/dev/stdin', 'utf8'));
//  [javascript]
function main(input){
  var line = input[0].split(' ').sort();
  console.log(line.join('') ==='1479' ? 'YES' : 'NO' );
}


var input = '';

process.stdin.resume();
process.stdin.setEncoding('utf8');
process.stdin.on('data', function(chunk) {
  input += chunk;
});
process.stdin.on('end', function() {
  input = input.split('\n');
  main(input);
});
//  [go]
package main

import (
  "fmt"
)

func main() {
  var n int
  num := make([]int, 10)
  
  for i := 0; i < 4; i++ {
    fmt.Scanf("%d", &n)
    num[n]++
  }
  
  ans := "YES"
  if num[1] != 1 {
    ans = "NO"
  }
  if num[9] != 1 {
    ans = "NO"
  }
  if num[7] != 1 {
    ans = "NO"
  }
  if num[4] != 1 {
    ans = "NO"
  }
  fmt.Printf("%s\n", ans)
}
//  [ruby]
n = gets.chomp.split.map(&:to_i)
ans = true
[1, 9, 7, 4].each do |e|
    ans = false unless n.include?(e)
end
puts ans ? "YES" : "NO"
//  [ruby]
a=gets.split.sort*''
puts a=="1479" ? :YES : :NO
//  [ruby]
n = gets.chomp.split.sort
puts (n == '1974'.split("").sort) ? "YES" : "NO"
//  [rust]
#[allow(unused_imports)]
use itertools::Itertools;
use proconio::input;
#[allow(unused_imports)]
use proconio::marker::*;

fn main() {
    input! {
        mut a: [i64; 4],
    }
    a.sort();
    if &a == &[1, 4, 7, 9] {
        println!("YES");
    } else {
        println!("NO");
    }
    // println!("{}", );
}
//  [rust]
use std::io::{stdin, Read, StdinLock};
use std::str::FromStr;

// reference: http://ir5.hatenablog.com/entry/20171209/1512821837

struct Scanner<'a> {
    cin: StdinLock<'a>,
}
 
impl<'a> Scanner<'a> {
    fn new(cin: StdinLock<'a>) -> Scanner<'a> {
        Scanner { cin: cin }
    }
 
    fn read1<T: FromStr>(&mut self) -> Option<T> {
        let token = self.cin.by_ref().bytes().map(|c| c.unwrap() as char)
            .skip_while(|c| c.is_whitespace())
            .take_while(|c| !c.is_whitespace())
            .collect::<String>();
        token.parse::<T>().ok()
    }
 
    fn read<T: FromStr>(&mut self) -> T {
        self.read1().unwrap()
    }
}

use std::mem;
use std::cmp;

fn main() {
    let cin = stdin();
    let cin = cin.lock();
    let mut sc = Scanner::new(cin);

    let mut a = vec![false; 10];
    for i in 0..4 {
        let x: usize = sc.read();
        a[x] = true;
    }
    if a[1] && a[4] && a[9] && a[7] {
        println!("{}", "YES");
    } else {
        println!("{}", "NO");
    }
}
//  [rust]
#![allow(unused_macros)]
#![allow(dead_code)]
#![allow(unused_imports)]

use itertools::Itertools;
use proconio::*;
use text_io::*;

const U_INF: usize = 1 << 60;
const I_INF: isize = 1 << 60;

fn main() {
    let mut str = String::new();
    for _ in 0..4 {
        str.push(read!());
    }

    let ans = if &str.chars().sorted().collect::<String>() == "1479" {
        "YES"
    } else {
        "NO"
    };

    println!("{}", ans);
}
//  [python]
try:
    from math import gcd
except:
    from fractions import gcd
import operator
from collections import deque


class Segtree:
    """
    st = Segtree(4, f=operator.add, e=0)
    st[1:] = [4, 9, 16]
    st[0] = -99
    assert st[-1] == 16
    assert st[:] == [-99, 4, 9, 16]
    assert st.grasp(1, 3) == 13
    """

    def __init__(self, n, f=operator.add, e=0):
        """all(f(v, e) == f(e, v) == v for v in data)"""
        self.r = range(n)
        self.size = 2 ** ((n - 1).bit_length())
        self.tree = [e] * (2 * self.size)
        self.f = f
        self.iden = e

    def __len__(self):
        return len(self.r)

    def __list__(self):
        return self.tree[self.size-1:self.size-1+len(self.r)]

    def __repr__(self):
        return repr(list(self))

    def grasp(self, i=0, j=None):
        """reduce(f, data[i:j], e)"""
        if j is None:
            j = len(self)
        i = self.size - 1 + max(i, 0)
        j = self.size - 1 + min(j, len(self))
        ans = self.iden
        while j - i > 0:
            if i & 1 is 0:
                ans = self.f(self.tree[i], ans)
            if j & 1 is 0:
                ans = self.f(ans, self.tree[j-1])
            i = i >> 1
            j = (j - 1) >> 1
        return ans

    def __getitem__(self, i):
        r = self.r[i]
        if isinstance(r, int):
            return self.tree[self.size - 1 + r]
        else:
            return [self.tree[self.size - 1 + ri] for ri in r]

    def __setitem__(self, i, v):
        """Extra elements will be ignored when i is a slice."""
        r = self.r[i]
        if isinstance(r, int):
            r = [r]
            v = [v]
        q = deque()
        s = set()

        def addnext(j):
            k = (j - 1) // 2
            if k >= 0 and k not in s:
                q.append(k)
                s.add(k)

        for ri, vi in zip(r, v):
            j = self.size - 1 + ri
            self.tree[j] = vi
            addnext(j)
        while len(q):
            j = q.popleft()
            # s.remove(j)
            vl = self.tree[2 * j + 1]
            vr = self.tree[2 * j + 2]
            self.tree[j] = self.f(vl, vr)
            addnext(j)


N = int(input())
A = [int(s) for s in input().split()]
st = Segtree(N, f=gcd, e=0)
st[:] = A
ans = max([gcd(st.grasp(0, i), st.grasp(i+1)) for i in range(N)])
print(ans)
//  [python]
import numpy as np
def gcd(a, b):
	if a < b:
		a, b = b, a
	if b == 0:
		return a
	else:
		return gcd(b, a % b)
n = int(input())
a = np.array([int(x) for x in input().split()])
np.sort(a)
l = np.zeros(n + 1)
r = np.zeros(n + 1)
m = np.zeros(n)
for i in range(n):
	l[i + 1] = gcd(l[i], a[i])
for i in reversed(range(n)):
	r[i] = gcd(r[i + 1], a[i])
for i in range(n):
	m[i] = gcd(l[i], r[i + 1])
print(int(np.max(m)))
//  [python]
def make_divisors(n):
    divisors = []
    for i in range(1, int(n**0.5)+1):
        if n % i == 0:
            divisors.append(i)
            if i != n // i:
                divisors.append(n//i)

    # divisors.sort()
    return divisors

#スペース入力
n = int(input())
a = input().split()

A = [int(element) for element in a]

A.sort()

a_min = A[0]
a_min2 = A[1]


a_min_divs = make_divisors(a_min)
a_min2_divs = make_divisors(a_min2)

a_min_divs.remove(1)
a_min2_divs.remove(1)

max_div = 1

results = [1]


for diver in a_min_divs:
    thr = 0
    for num in A:
        # print(num)
        # print(diver)
        # print(num % diver)
        if num % diver != 0:
            thr = thr+1
            if thr > 1:

                break
            else:
                continue
    if thr < 2:
        results.append(diver)

for diver in a_min2_divs:
    thr = 0
    for num in A:
        # print(num)
        # print(diver)
        # print(num % diver)
        if num % diver != 0:
            thr = thr+1
            if thr > 1:

                break
            else:
                continue
    if thr < 2:
        results.append(diver)



print(max(results))
//  [java]

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();

		int a[] = new int[100001];

		for(int i = 0; i < n; i++){
			a[i] = sc.nextInt();
		}

		int SEG_SIZE = 100;
		int seg[] = new int[a.length/SEG_SIZE];
		int gcdInSegWithout[] = new int[100001];

		for(int i = 0; i < n; i += SEG_SIZE){
			int tmpgcd = a[i];

			int segID = i / SEG_SIZE;
			for(int j = 0; j < SEG_SIZE; j++){
				if(segID*SEG_SIZE + j >= n){
					break;
				}


				tmpgcd = gcd(a[segID*SEG_SIZE + j], tmpgcd);
			}
			seg[segID] = tmpgcd;
		}
//
//		for(int i = 0; i < 10; i++){
//			System.out.print(seg[i]+" ");
//		}
//		System.out.println();

		for(int i = 0; i < n; i ++){
			int tmpgcd = 0;

			int segID = i / SEG_SIZE;
			for(int j = 0; j < SEG_SIZE; j++){
				if(segID*SEG_SIZE + j >= n){
					break;
				}

				if(segID*SEG_SIZE + j == i){
					continue;
				}

				if(tmpgcd == 0){
					tmpgcd = a[segID*SEG_SIZE + j];
				}
				else {
					tmpgcd = gcd(a[segID*SEG_SIZE + j], tmpgcd);
				}
			}
			gcdInSegWithout[i] = tmpgcd;
		}
//		for(int i = 0; i < 10; i++){
//			System.out.print(gcdInSegWithout[i]+" ");
//		}
//		System.out.println();

		int result = 0;
		for(int i = 0; i < n; i++){

			int segID = i / SEG_SIZE;
			int tmpgcd = gcdInSegWithout[i];

			for(int j = 0; j < seg.length; j++){
				if(j == segID || seg[j] == 0){
					continue;
				}

				if(tmpgcd == 0){
					tmpgcd = seg[j];
				}
				else {
					tmpgcd = gcd(tmpgcd, seg[j]);
				}
			}

			result = Math.max(result, tmpgcd);
		}

		System.out.println(result);

	}

	static int gcd(int a, int b){
    	int tmp;

    	while (a % b != 0)
    	{
    		tmp = b;
    		b = a % b;
    		a = tmp;
    	}
    	return b;
    }
}
//  [cpp]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
/* clang-format off */
#define INF (INT_MAX / 4)
#define REP(i, n) for (ll i = 0, i##_len = (n); i < i##_len; ++i)
#define ALL(a) (a).begin(), (a).end()
#define DEBUG(x) cout<<#x<<":"<<x<<"\n"
#define DEBUGS(v) cout << #v << ":";for(auto x:v){cout<<x<<" ";}cout<<"\n"
#define TIMER_S(start) chrono::system_clock::time_point start = chrono::system_clock::now();
#define TIMER_E(end) chrono::system_clock::time_point end = chrono::system_clock::now();
#define TIME(start, end) cout << static_cast<double>(chrono::duration_cast<chrono::microseconds>(end - start).count()) << "ms" << "\n";
/* clang-format on */

int main() {
  int n;
  cin >> n;
  vector<int> a(n), g_wo_i(n, 1);
  vector<queue<int>> factor(n);
  vector<pair<int, int>> prime;
  for (auto &x : a) {
    cin >> x;
  }

  // g1は全要素の最大公約数
  int g1 = a.at(0);
  for (auto &x : a) {
    g1 = __gcd(g1, x);
  }
  for (auto &x : a) {
    x /= g1;
  }

  //√max(a)までの素数を生成
  int check_num = (int)sqrt(*max_element(ALL(a)));
  vector<bool> is_prime(check_num + 1, true);
  for (int i = 0; i <= check_num; i++) {
    if (i == 0 || i == 1) is_prime.at(i) = false;
    if (is_prime.at(i)) {
      for (int j = i + 1; j <= check_num; j++) {
        if (j % i == 0) is_prime.at(j) = false;
      }
    }
  }
  REP(i, check_num + 1) {
    if (is_prime.at(i)) prime.push_back(make_pair(i, 0));
  }

  // aを素因数分解,素因数をfactorに格納
  REP(i, n) {
    for (auto &y : prime) {
      int cnt = 0;
      while (a.at(i) % y.first == 0) {
        cnt++;
        factor.at(i).push(y.first);
        a.at(i) /= y.first;
      }
      y.second = max(y.second, cnt);
      if (a.at(i) == 1) break;
    }
    if (a.at(i) != 1) {
      factor.at(i).push(a.at(i));
      prime.push_back(make_pair(a.at(i), 0));
    }
  }
  sort(ALL(prime));

  //一つを除いた最大公約数を求める
  for (auto y : prime) {
    int p = y.first;
    int p_n = y.second;
    REP(i, p_n) {
      int cnt = 0;
      int tmp;
      REP(j, n) {
        if (factor.at(j).empty()) {
          cnt++;
          tmp = j;
        } else {
          if (factor.at(j).front() == p) {
            factor.at(j).pop();
          } else {
            cnt++;
            tmp = j;
          }
        }
      }
      if (cnt == 1) {
        g_wo_i.at(tmp) *= p;
      }
    }
  }

  cout << g1 * *max_element(ALL(g_wo_i)) << "\n";
  return 0;
}
//  [cpp]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
/* clang-format off */
#define INF (INT_MAX / 4)
#define REP(i, n) for (ll i = 0, i##_len = (n); i < i##_len; ++i)
#define ALL(a) (a).begin(), (a).end()
#define DEBUG(x) cout<<#x<<":"<<x<<"\n"
#define DEBUGS(v) cout << #v << ":";for(auto x:v){cout<<x<<" ";}cout<<"\n"
#define TIMER_S(start) chrono::system_clock::time_point start = chrono::system_clock::now();
#define TIMER_E(end) chrono::system_clock::time_point end = chrono::system_clock::now();
#define TIME(start, end) cout << static_cast<double>(chrono::duration_cast<chrono::microseconds>(end - start).count()) << "ms" << "\n";
/* clang-format on */

int main() {
  int n;
  cin >> n;
  vector<int> a(n), g_wo_i(n, 1);
  // vector<vector<int>> factor(n);
  vector<queue<int>> factor2(n);
  vector<pair<int, int>> prime;
  // srand((unsigned int)time(NULL));
  for (auto &x : a) {
    cin >> x;
    // x = rand()%1000000000;
  }

  // g1は全要素の最大公約数
  int g1 = a.at(0);
  for (auto &x : a) {
    g1 = __gcd(g1, x);
  }
  for (auto &x : a) {
    x /= g1;
  }

  //√max(a)までの素数を生成
  int check_num = (int)sqrt(*max_element(ALL(a)));
  vector<bool> is_prime(check_num + 1, true);
  for (int i = 0; i <= check_num; i++) {
    if (i == 0 || i == 1) is_prime.at(i) = false;
    if (is_prime.at(i)) {
      for (int j = i + 1; j <= check_num; j++) {
        if (j % i == 0) is_prime.at(j) = false;
      }
    }
  }
  REP(i, check_num + 1) {
    if (is_prime.at(i)) prime.push_back(make_pair(i, 0));
  }

  // aを素因数分解,素因数をfactorに格納
  REP(i, n) {
    for (auto &y : prime) {
      int cnt = 0;
      while (a.at(i) % y.first == 0) {
        cnt++;
        factor2.at(i).push(y.first);
        // factor.at(i).push_back(y.first);
        a.at(i) /= y.first;
      }
      y.second = max(y.second, cnt);
      if (a.at(i) == 1) break;
    }
    if (a.at(i) != 1) {
      factor2.at(i).push(a.at(i));
      prime.push_back(make_pair(a.at(i), 0));
      // factor.at(i).push_back(a.at(i));
    }
  }
  sort(ALL(prime));

  // DEBUGS(is_prime);
  // DEBUG(check_num);
  // REP(i, n) { DEBUGS(factor.at(i)); }

  //一つを除いた最大公約数を求める
  for (auto y : prime) {
    int p = y.first;
    int p_n = y.second;
    REP(i, p_n) {
      int cnt = 0;
      int tmp;
      REP(j, n) {
        // if (factor.at(j).size() == 0) {
        if (factor2.at(j).empty()) {
          cnt++;
          tmp = j;
        } else {
          // if (factor.at(j).at(0) == p) {
          if (factor2.at(j).front() == p) {
            // factor.at(j).erase(factor.at(j).begin());
            factor2.at(j).pop();
          } else {
            cnt++;
            tmp = j;
          }
        }
      }
      if (cnt == 1) {
        g_wo_i.at(tmp) *= p;
      }
    }
  }

  // DEBUGS(g_wo_i);
  //  DEBUG(g1);
  // DEBUGS(prime);
  cout << g1 * *max_element(ALL(g_wo_i)) << "\n";
  return 0;
}
//  [cpp]
#include <bits/stdc++.h>
using namespace std;

int main(){
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0;i < n;i ++){
        cin >> a.at(i);
    }
    sort(a.begin(),a.end());
    int kou_n = 1;

    for(int i = a.at(0);i > 1;i --){
        for(int j = 0;j < n;j ++){
            if(a.at(j) % i != 0){
                break;
            }else if(j == n-1){
                kou_n = i;
                break;
            }
        }
        if(kou_n == 1){
            continue;
        }else{
            break;
        }
    }
    
    int kou_n_1 = kou_n;
    int cnt;
    for(int i = a.at(1);i >= kou_n;i --){
        cnt = 0;
        for(int j = 0;j < n;j ++){
            if(a.at(j) % i != 0){
                cnt ++;
            }
            if(cnt > 1){
                break;
            }else if(j == n-1){
                kou_n_1 = i;
            }
        }
        if(kou_n_1 > kou_n){
            break;
        }
    }

    cout << kou_n_1 << endl;
}
//  [c]
#include <stdio.h>

int count(int *a, int num, int b) {
    int count = 0;
    for (int i=0; i<num; i++) {
        if (a[i]%b != 0) count++;
    }
    if (count > 1) return 0;
    return 1;
}

int main() {
    int num = 0;
    scanf("%d\n", &num);
    int a[num];
    for (int i=0; i<num; i++) {
        scanf("%d", a+i);
    }
    int min = 0, min2 = 0;
    if (a[0] > a[1]) min = a[1], min2 = a[0];
    else min = a[0], min2 = a[1];
    for (int i=2; i<num; i++) {
        if (a[i] < min) min = a[i];
        else if (a[i] < min2) min2 = a[i];
    }
    int max = 0;
    if (num == 2) printf("%d\n", min2);
    else {
        for (int i=min; i>0; i--) {
            if (min%i == 0) {
                if (count(a, num, i)) {
                    max = i;
                    break;
                }
            }
        }
        for (int i=min2; i>0; i--) {
            if (min2%i == 0) {
                if (count(a, num, i)) {
                    if (i > max) max = i;
                    break;
                }
            }
        }
        printf("%d\n", max);
    }
    return 0;
}
//  [c]
#include <stdio.h>

int count(int *a, int num, int b) {
    int count = 0;
    for (int i=0; i<num; i++) {
        if (a[i]%b != 0) count++;
        if (count > 1) return 0;
    }
    return 1;
}

int main() {
    int num = 0;
    scanf("%d\n", &num);
    int a[num];
    for (int i=0; i<num; i++) {
        scanf("%d", a+i);
    }
    int min = 0, min2 = 0;
    if (a[0] > a[1]) min = a[1], min2 = a[0];
    else min = a[0], min2 = a[1];
    for (int i=2; i<num; i++) {
        if (a[i] < min) min = a[i];
        else if (a[i] < min2) min2 = a[i];
    }
    int max = 0;
    if (num == 2) printf("%d\n", min2);
    else {
        for (int i=min; i>0; i--) {
            if (min%i == 0) {
                if (count(a, num, i)) {
                    max = i;
                    break;
                }
            }
        }
        for (int i=min2; i>max; i--) {
            if (min2%i == 0) {
                if (count(a, num, i)) {
                    if (i > max) max = i;
                    break;
                }
            }
        }
        printf("%d\n", max);
    }
    return 0;
}
//  [c]
#include <stdio.h>

int count(int *a, int num, int b) {
    int count = 0;
    for (int i=0; i<num; i++) {
        if (a[i]%b != 0) count++;
        if (count > 1) return 0;
    }
    return 1;
}

int main() {
    int num = 0;
    scanf("%d\n", &num);
    int a[num];
    for (int i=0; i<num; i++) {
        scanf("%d", a+i);
    }
    int min = 0, min2 = 0;
    if (a[0] > a[1]) min = a[1], min2 = a[0];
    else min = a[0], min2 = a[1];
    for (int i=2; i<num; i++) {
        if (a[i] < min) min = a[i];
        else if (a[i] < min2) min2 = a[i];
    }
    int max = 0;
    if (num == 2) printf("%d\n", min2);
    else {
        for (int i=min; i>0; i--) {
            if (min%i == 0) {
                if (count(a, num, i)) {
                    max = i;
                    break;
                }
            }
        }
        for (int i=min2; i>0; i--) {
            if (min2%i == 0) {
                if (count(a, num, i)) {
                    if (i > max) max = i;
                    break;
                }
            }
        }
        printf("%d\n", max);
    }
    return 0;
}
//  [javascript]
function checkAll(div, As) {
    var mod = 0
    var result = true;
    As.forEach(element => {
        if (element % div > 0) {
            mod++;
            if (mod > 1) {
                result = false;
            }
        }
    });
    return result;
}

function Main(input) {
    const N = parseInt(input.shift());
    var As = input.map(x => parseInt(x));

    As = As.sort((a, b) => { return a - b; }); // 昇順ソート

    var firstDiv = 0;
    var secondDiv = 0;

    for (var div = As[0]; div > 0; div--) {
        if (As[0] % div == 0) {
            // 約数なら
            if (checkAll(div, As)) {
                firstDiv = div;
                break;
            }
        }
    }

    for (var div = As[1]; div > firstDiv; div--) {
        if (As[1] % div == 0) {
            // 約数なら
            if (checkAll(div, As)) {
                secondDiv = div;
                break;
            }
        }
    }

    console.log(Math.max(firstDiv, secondDiv));
}

// 改行・空白で分割
Main(require("fs").readFileSync("/dev/stdin", "utf8").trim().split(/\n|\s/));
//  [javascript]
// inputに入力データ全体が入る
function Main(input) {
    // 1行目がinput[0], 2行目がinput[1], …に入る
    input = input.split("\n");
    // 数値の配列を作る
    const numList0 = input[0].split(' ').map(x => parseInt(x, 10));
    const N = numList0[0];
    const aList = input[1].split(' ').map(x => parseInt(x, 10));

    const gcd = function(a, b) {
        if ( ! b) {
            return a;
        }
    
        return gcd(b, a % b);
    };

    const lList = [0];
    const rList = [0];
    var newL = 0;
    var newR = 0;
    for (var i = 0; i < N; i++) {
        newL = gcd(newL, aList[i]);
        lList.push(newL);
        newR = gcd(newR, aList[N - i - 1]);
        rList.unshift(newR);
    }

    var max = 0;
    for (var i = 0; i < N; i++) {
        var result = gcd(lList[i], rList[i + 1]);
        max = Math.max(max, result);
    }

    console.log(max);
}

Main(require("fs").readFileSync("/dev/stdin", "utf8"));
//  [go]
package main

import (
	"fmt"
	"math"
	"math/big"
)

func main() {
	var n int
	fmt.Scan(&n)
	arr := make([]int, n)
	for i := 0; i < n; i++ {
		var tmp int
		fmt.Scan(&tmp)
		arr[i] = tmp
	}
	l, r := make([]int, n), make([]int, n)
	l[0], r[n - 1] = arr[0], arr[n - 1]
	for i := 1; i < n; i++ {
		l[i], r[n - i - 1] = gcd(l[i - 1], arr[i]), gcd(r[n - i], arr[n - i - 1])
	}
	max := math.MinInt32
	for i := 0; i < n; i++ {
		var ll, rr int
		if i - 1 >= 0 {
			ll = l[i - 1]
		}
		if i + 1 <= n - 1 {
			rr = r[i + 1]
		}
		var tmp int
		if ll == 0 {
			tmp = rr
		} else if rr == 0 {
			tmp = ll
		} else {
			tmp = gcd(ll, rr)
		}
		if max < tmp {
			max = tmp
		}
	}
	fmt.Println(max)
}


func gcd(m, n int) int {
	x := new(big.Int)
	y := new(big.Int)
	z := new(big.Int)
	a := new(big.Int).SetUint64(uint64(m))
	b := new(big.Int).SetUint64(uint64(n))
	return int(z.GCD(x, y, a, b).Uint64())
}
//  [go]
package main

import (
	"fmt"
	"math"
	"sort"
)

type Num struct {
	value  int
	factor map[int]int
}

func NewNum(i int) *Num {
	num := &Num{}
	num.value = i
	num.factor = make(map[int]int)
	//	num.primeFactors()
	return num
}

func calcGCD(a, b int) int {
	if b == 0 {
		return a
	} else {
		return calcGCD(b, a%b)
	}
}

func (n *Num) primeFactors() {
	num := n.value
	i := 2
	for i*i <= num {
		if num%i == 0 {
			num /= i
			n.factor[i] += 1
		} else {
			i += 1
		}
	}
	if num != 1 {
		n.factor[num] += 1
	}
}

func getMin(divisor []int, length int) (min, nextMin int) {
	switch {
	case len(divisor) <= length-2:
		min = 0
		nextMin = 0
	case len(divisor) == length-1:
		sort.Ints(divisor)
		min = 0
		nextMin = divisor[0]
	default:
		sort.Ints(divisor)
		min = divisor[0]
		nextMin = divisor[1]
	}
	return min, nextMin
}

func getGCD(A []*Num) int {
	factors := make(map[int][]int)
	for _, a := range A {
		for value, count := range a.factor {
			if _, ok := factors[value]; !ok {
				factors[value] = make([]int, 0, 0)
			}
			factors[value] = append(factors[value], count)
		}
	}
	max := 0.0
	gcd := 1
	for value, factor := range factors {
		min, nextMin := getMin(factor, len(A))
		gcd *= int(math.Pow(float64(value), float64(min)))
		tmpMax := math.Pow(float64(value), float64(nextMin-min))
		if max < tmpMax {
			max = tmpMax
		}
	}
	return gcd * int(max)
}

func main() {
	var N int
	fmt.Scan(&N)
	A := make([]*Num, 0, N)
	var input int
	for i := 0; i < N; i++ {
		fmt.Scan(&input)
		A = append(A, NewNum(input))
	}
	max := 0
	var gcd int
	cacheGCDFromStart := make([]int, 0, N)
	cacheGCDFromEnd := make([]int, 0, N)
	gcd = A[0].value
	cacheGCDFromStart = append(cacheGCDFromStart, gcd)
	for i := 1; i < N; i++ {
		gcd = calcGCD(gcd, A[i].value)
		cacheGCDFromStart = append(cacheGCDFromStart, gcd)
	}

	gcd = A[N-1].value
	for i := N - 1; i >= 0; i-- {
		gcd = calcGCD(gcd, A[i].value)
		cacheGCDFromEnd = append(cacheGCDFromEnd, gcd)
	}
	max = cacheGCDFromEnd[N-2]
	if max < cacheGCDFromStart[N-2] {
		max = cacheGCDFromStart[N-2]
	}
	/*
		fmt.Println(cacheGCDFromStart)
		fmt.Println(cacheGCDFromEnd)
	*/

	for i := 1; i < N-1; i++ {
		gcd = calcGCD(cacheGCDFromStart[i-1], cacheGCDFromEnd[N-2-i])
		if max < gcd {
			max = gcd
		}
	}
	fmt.Println(max)

}
//  [go]
package main

import (
	"fmt"
)

func gcd(a, b int) int {
	if b == 0 {
		return a
	}
	return gcd(b, a%b)
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}
func main() {
	var n int
	fmt.Scanln(&n)
	a := make([]int, n)
	for i := 0; i < n; i++ {
		fmt.Scan(&a[i])
	}
	gcd_l := make([]int, n)
	gcd_r := make([]int, n)
	gcd_l[0] = a[0]
	for i := 1; i < n; i++ {
		gcd_l[i] = gcd(gcd_l[i-1], a[i])
	}
	gcd_r[n-1] = a[n-1]
	for i := n - 2; i >= 0; i-- {
		gcd_r[i] = gcd(gcd_r[i+1], a[i])
	}
	ans := max(gcd_l[n-2], gcd_r[1])
	for i := 1; i < n-1; i++ {
		g := gcd(gcd_l[i-1], gcd_r[i+1])
		if g > ans {
			ans = g
		}
	}
	fmt.Println(ans)
}
//  [ruby]
##templete
n = gets.chomp.to_i
a = gets.chomp.split(" ").map { |e| e.to_i }.sort

def div_array(x, res)
  index = 0
  num = 100000
  num.times do |i|
    if x % (i+1) == 0
      res[index] = i+1
      res[index+1] = x/(i+1)
      index += 2
    end
  end
  res.sort.uniq
end

lst0 = div_array(a[0], [])
lst1 = div_array(a[1], [])
lst = (lst0 + lst1).uniq

hash = {}

for x in lst do
  hash[x] = 0
end

for num in a do
  for x in lst do
    if num % x == 0
      hash[x] += 1
    end
  end
end

ans = 0

for i in lst.reverse do
  if hash[i] == n-1 || hash[i] == n
    puts i
    exit 0
  end
end
//  [ruby]
class Segtree
  attr_reader :dat
  def initialize(n)
    @n = 1
    while @n < n
      @n *= 2
    end
    @dat = {}
  
    (@n * 2 - 1).times do |i|
      # @dat[i] = Float::INFINITY
      @dat[i] = 0
    end
  end

  # k番目(0-indexed)の値をaに変更
  # def update(k, a)
  #   k += @n - 1
  #   @dat[k] = a

  #   while k > 0
  #     k = (k - 1) / 2
  #     @dat[k] = [@dat[k * 2 + 1], @dat[k * 2 + 2]].min
  #   end
  # end
  def update(k, a)
    k += @n - 1
    @dat[k] = a

    while k > 0
      k = (k - 1) / 2
      @dat[k] = @dat[k * 2 + 1].gcd(@dat[k * 2 + 2])
    end
  end

  # [a, b)の最小値を求める
  def query(a, b, k = 0,l = 0, r = @n)
    return Float::INFINITY if r <= a || b <= l
    return @dat[k] if a <= l && r <= b
    vl = query(a,b,k * 2 + 1, l, (l + r) / 2)
    vr = query(a,b,k * 2 + 2, (l + r) / 2, r)
    [vl, vr].min
  end
end

n = gets.to_i
as = gets.split.map(&:to_i)
if n.odd?
  s = Segtree.new(n+1)
else
  s = Segtree.new(n)
end

as.each.with_index do |a,i|
  s.update(i,a)
end

ans = 1
as.each.with_index do |a,i|
  s.update(i,0)
  ans = [ans, s.dat[0]].max
  s.update(i,a)
end

puts ans
//  [ruby]
class SegmentTree
  ROOT = 1
  private_constant :ROOT

  attr_reader :size

  def initialize(n, x = 0)
    @size = 1
    @size *= 2 while @size < n
    @sum = Array.new(2 * @size){x}
  end

  def update(i, v)
    i += @size
    @sum[i] = v
    until i == ROOT
      i = i / 2
      @sum[i] = @sum[2*i].gcd(@sum[2*i+1])
    end
  end

  def sum(l, r)
    sum_dfs(l, r, ROOT, 0, @size)
  end
  def sum_dfs(a, b, i, l, r)
    return 0       if b <= l || r <= a
    return @sum[i] if a <= l && r <= b
    sum_dfs(a, b, 2*i, l, (l+r)/2).gcd(sum_dfs(a, b, 2*i+1, (l+r)/2, r))
  end
end

N=gets.to_i
A=gets.split.map &:to_i

segtree = SegmentTree.new(N)
A.each.with_index do |a, i|
  segtree.update(i, a)
end
res = 0
N.times do |i|
  l = i.zero? ? 0 : segtree.sum(0, i)
  r = i+1==N  ? 0 : segtree.sum(i+1, N)
  d = l.gcd(r)
  res = [res, d].max
end
p res
//  [rust]
#[allow(unused_macros)]
macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        let mut next = || { iter.next().unwrap() };
        input_inner!{next, $($r)*}
    };
    ($($r:tt)*) => {
        let stdin = std::io::stdin();
        let mut bytes = std::io::Read::bytes(std::io::BufReader::new(stdin.lock()));
        let mut next = move || -> String{
            bytes
                .by_ref()
                .map(|r|r.unwrap() as char)
                .skip_while(|c|c.is_whitespace())
                .take_while(|c|!c.is_whitespace())
                .collect()
        };
        input_inner!{next, $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! input_inner {
    ($next:expr) => {};
    ($next:expr, ) => {};

    ($next:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };

    ($next:expr, mut $var:ident : $t:tt $($r:tt)*) => {
        let mut $var = read_value!($next, $t);
        input_inner!{$next $($r)*}
    };
}

#[allow(unused_macros)]
macro_rules! read_value {
    ($next:expr, ( $($t:tt),* )) => {
        ( $(read_value!($next, $t)),* )
    };

    ($next:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($next, $t)).collect::<Vec<_>>()
    };

    ($next:expr, chars) => {
        read_value!($next, String).chars().collect::<Vec<char>>()
    };

    ($next:expr, bytes) => {
        read_value!($next, String).into_bytes()
    };

    ($next:expr, usize1) => {
        read_value!($next, usize) - 1
    };

    ($next:expr, $t:ty) => {
        $next().parse::<$t>().expect("Parse error")
    };
}

use std::collections::HashMap;

fn main() {
    let mut primes: Vec<i64> = vec![];
    let mut sieve = vec![true; 31623];

    for i in 2..sieve.len() {
        if sieve[i] {
            primes.push(i as i64);
            let mut j = i + i;
            while j < sieve.len() {
                sieve[j] = false;
                j += i;
            }
        }
    }

    input! {
        n: usize,
        a: [i64; n],
    }

    let mut m = HashMap::new();

    for a in a {
        let mut a = a;
        let mut fs = vec![];

        for &p in primes.iter() {
            if p * p > a {
                break;
            }

            let mut cnt = 0;
            while a % p == 0 {
                a /= p;
                cnt += 1;
            }
            if cnt > 0 {
                fs.push((p, cnt));
            }
        }

        if a > 1 {
            fs.push((a, 1));
        }

        // println!("{}: {:?}", a, fs);

        rec(0, 1, &fs, &mut m);
    }

    // println!("{:?}", m);

    let mut ans = 1;

    for (k, cnt) in m {
        if cnt >= n - 1 {
            ans = std::cmp::max(ans, k);
        }
    }

    println!("{}", ans);
}

fn rec(i: usize, acc: i64, fs: &[(i64, usize)], m: &mut HashMap<i64, usize>) {
    if i >= fs.len() {
        *m.entry(acc).or_insert(0) += 1;
        return;
    }

    let mut t = acc;
    for _ in 0..fs[i].1 + 1 {
        rec(i + 1, t, fs, m);
        t *= fs[i].0;
    }
}
//  [typescript]
function main(input) {
  input = input.trim().split("\n");
  const n = Number(input[0]);
  const a = input[1].split(" ").map(n => Number(n));
  const gcd = (a, b) => {
    if (b === 0) return a;
    return gcd(b, a%b);
  }
  const l = [];
  for (let i = 0; i < n; i++) {
    if (i === 0) {
      l.push(a[i]);
      continue;
    }
    l.push(gcd(l[l.length-1], a[i]));
  }
  
  const r = [];
  for (let i = n - 1; 0 <= i; i--) {
    if (i === n-1) {
      r.unshift(a[i]);
      continue;
    }
    r.unshift(gcd(r[0], a[i]));
  }
  
  let result = 0;
  for (let i = 0; i < n; i++) {
    const num = gcd(i === 0 ? 0 : l[i-1], i === n-1 ? 0 : r[i+1]);
    if (result < num) result = num;
  }
  console.log(result);
}
main(require("fs").readFileSync("/dev/stdin", "utf8"));