#pragma GCC target("avx2") #pragma GCC optimize("O3") #pragma GCC optimize("unroll-loops") #include #include #include using namespace std; // ユーザ定義の gcd 関数(ユークリッドの互除法) long long gcd(long long a, long long b) { while (b != 0) { long long temp = a % b; a = b; b = temp; } return a; } // グローバル変数 int N; vector A; // __int128 を使って積の比較を安全に行う関数 bool comp(long long x_c, long long x_d, long long y_c, long long y_d) { __int128 lhs = (__int128)x_c * y_d; __int128 rhs = (__int128)y_c * x_d; return lhs <= rhs; } // check 関数: 与えられた val に対して (bool, (max_c, max_d)) を返す pair> check(long long val) { long long max_c = 0, max_d = 1; long long cnt = 0; for (int i = 0; i < N; i++) { int ok = 0, ng = N; // バイナリサーチ: 条件を満たす最大の ok を求める while (ng - ok > 1) { int mid = (ok + ng) / 2; // Python の comp((A[mid-1], A[i]), (val, 2 * 10**18)) に対応 if (comp(A[mid - 1], A[i], val, 2000000000000000000LL)) { ok = mid; } else { ng = mid; } } cnt += ok; // 条件により最大の分数 (max_c, max_d) を更新 if (ok > 0 && comp(max_c, max_d, A[ok - 1], A[i])) { max_c = A[ok - 1]; max_d = A[i]; } } // ペア数が N*(N-1)/2 未満なら true、それ以外なら false を返す if (cnt < (long long)N * (N - 1) / 2) { return {true, {max_c, max_d}}; } else { return {false, {max_c, max_d}}; } } int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); // 入力 cin >> N; A.resize(N); for (int i = 0; i < N; i++) { cin >> A[i]; } // ソート sort(A.begin(), A.end()); // main のバイナリサーチ: [0, 2*10^18+1) の範囲で val を探索 long long ok_val = 0, ng_val = 2000000000000000000LL + 1; while (ng_val - ok_val > 1) { long long mid = (ok_val + ng_val) / 2; if (check(mid).first) { ok_val = mid; } else { ng_val = mid; } } // 答えの分数を得る auto ans = check(ng_val).second; long long g = gcd(ans.first, ans.second); cout << (ans.first / g) << " " << (ans.second / g) << "\n"; return 0; }