#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1);
struct myHash {
  template <class T1, class T2>
  size_t operator()(const pair<T1, T2>& p) const {
    auto hash1 = hash<T1>{}(p.first);
    auto hash2 = hash<T2>{}(p.second);
    return hash1 ^ hash2;
  }
};
class segTree {
  vector<long long int> a;
  vector<long long int> tree;
  vector<long long int> lazy;
  long long int sel;
  long long int minRange(long long int left, long long int right) {
    return min(left, right);
  }
  long long int maxRange(long long int left, long long int right) {
    return max(left, right);
  }
  long long int rangeSum(long long int left, long long int right) {
    return left + right;
  }
  void build(long long int index, long long int start, long long int end) {
    if (start > end) {
      return;
    }
    if (start == end) {
      tree[index] = a[start];
      return;
    }
    long long int mid = (start + end) / 2;
    build(2 * index, start, mid);
    build(2 * index + 1, mid + 1, end);
    long long int left = tree[2 * index];
    long long int right = tree[2 * index + 1];
    if (sel == 0) {
      tree[index] = minRange(tree[2 * index], tree[2 * index + 1]);
    } else if (sel == 1) {
      tree[index] = maxRange(tree[2 * index], tree[2 * index + 1]);
    } else if (sel == 2) {
      tree[index] = rangeSum(tree[2 * index], tree[2 * index + 1]);
    }
  }
  long long int query(long long int index, long long int start,
                      long long int end, long long int l, long long int r) {
    if (lazy[index] != 0) {
      if (sel == 0) {
        tree[index] += lazy[index];
      } else if (sel == 1) {
        tree[index] += lazy[index];
      } else if (sel == 2) {
        tree[index] += (end - start + 1) * lazy[index];
      }
      if (start != end) {
        lazy[2 * index] += lazy[index];
        lazy[2 * index + 1] += lazy[index];
      }
      lazy[index] = 0;
    }
    if (l > end || r < start) {
      if (sel == 0) {
        return LLONG_MAX;
      } else if (sel == 1) {
        return LLONG_MIN;
      } else if (sel == 2) {
        return 0;
      }
    }
    if (start >= l && end <= r) {
      return tree[index];
    }
    long long int mid = (start + end) / 2;
    long long int left = query(2 * index, start, mid, l, r);
    long long int right = query(2 * index + 1, mid + 1, end, l, r);
    if (sel == 0) {
      return minRange(left, right);
    } else if (sel == 1) {
      return maxRange(left, right);
    } else if (sel == 2) {
      return rangeSum(left, right);
    }
  }
  void update(long long int index, long long int start, long long int end,
              long long int l, long long int r, long long int inc) {
    if (lazy[index] != 0) {
      if (sel == 0) {
        tree[index] += lazy[index];
      } else if (sel == 1) {
        tree[index] += lazy[index];
      } else if (sel == 2) {
        tree[index] += (r - l + 1) * lazy[index];
      }
      if (start != end) {
        lazy[2 * index] += lazy[index];
        lazy[2 * index + 1] += lazy[index];
      }
      lazy[index] = 0;
    }
    if (l <= start and end <= r) {
      if (sel == 0) {
        tree[index] += inc;
      } else if (sel == 1) {
        tree[index] += inc;
      } else {
        tree[index] += (end - start + 1) * inc;
      }
      if (start != end) {
        lazy[2 * index] += inc;
        lazy[2 * index + 1] += inc;
      }
      return;
    }
    if (r < start || l > end) {
      return;
    }
    if (start == end) {
      tree[index] += inc;
      return;
    }
    long long int mid = (start + end) / 2;
    update(2 * index, start, mid, l, r, inc);
    update(2 * index + 1, mid + 1, end, l, r, inc);
    if (sel == 0) {
      tree[index] = minRange(tree[2 * index], tree[2 * index + 1]);
    } else if (sel == 1) {
      tree[index] = maxRange(tree[2 * index], tree[2 * index + 1]);
    } else if (sel == 2) {
      tree[index] = rangeSum(tree[2 * index], tree[2 * index + 1]);
    }
  }

 public:
  segTree(vector<long long int> a, long long int sel) {
    this->a = a;
    tree.reserve(4 * a.size() + 1);
    lazy.reserve(4 * a.size() + 1);
    for (int i = 0; i < 4 * a.size() + 1; i++) {
      lazy[i] = 0;
    }
    this->sel = sel;
  }
  void build() { build(1, 0, a.size() - 1); }
  long long int query(long long int l, long long int r) {
    return query(1, 0, a.size() - 1, l, r);
  }
  void update(long long int l, long long int r, long long int inc) {
    update(1, 0, a.size() - 1, l, r, inc);
  }
  void update(long long int pos, long long int inc) { update(pos, pos, inc); }
};
long long int power(long long int b, long long int p,
                    long long int m = 1000000007) {
  long long int res = 1;
  while (p > 0) {
    if (p & 1) {
      res = (res * b) % m;
    }
    b = (b * b) % m;
    p = p >> 1;
  }
  return res;
}
long long int modInverse(long long int n, long long int m = 1000000007) {
  return power(n, m - 2, m);
}
bool mySort(pair<int, int> p1, pair<int, int> p2) {
  if (p1.first < p2.first) {
    return true;
  } else if (p1.first == p2.first and p1.second < p2.second) {
    return true;
  }
  return false;
}
long long int lis(vector<long long int>& v) {
  long long int n = v.size();
  vector<long long int> dp(n);
  dp[0] = 1;
  long long int ans = 1;
  for (int i = 1; i < n; i++) {
    long long int m = 0;
    for (int j = i - 1; j >= 0; j--) {
      if (v[j] < v[i]) {
        m = max(m, dp[j]);
      }
    }
    dp[i] = 1 + m;
    if (ans < dp[i]) {
      ans = dp[i];
    }
  }
  return ans;
}
vector<long long int> sieve(long long int n) {
  vector<bool> v(n + 1, false);
  v[2] = true;
  for (int i = 3; i <= n; i += 2) {
    v[i] = true;
  }
  for (size_t i = 3; i <= n; i += 2) {
    if (v[i]) {
      for (size_t j = i * i; j <= n; j += 2 * i) {
        v[j] = false;
      }
    }
  }
  v[1] = false;
  v[0] = false;
  vector<long long int> primes;
  for (int i = 0; i < v.size(); i++) {
    if (v[i]) {
      primes.push_back(i);
    }
  }
  return primes;
}
long long int gcd(long long int a, long long int b) {
  while (b > 0) {
    long long int r = a % b;
    a = b;
    b = r;
  }
  return a;
}
long long int lcm(long long int a, long long int b) {
  long long int g = gcd(a, b);
  return (a * b) / g;
}
vector<long long int> segSieve(long long int l, long long int r) {
  long long int lim = sqrt(r);
  if (l < 2) {
    l = 2;
  }
  vector<long long int> s = sieve(lim);
  vector<bool> v(r - l + 1, true);
  for (long long int i = 0; i < s.size(); i++) {
    for (long long int j = 0; j < v.size(); j++) {
      if ((j + l) % s[i] == 0 && (j + l) != s[i]) {
        v[j] = false;
      }
    }
  }
  vector<long long int> primes;
  for (int i = 0; i < v.size(); i++) {
    if (v[i]) {
      primes.push_back(i + l);
    }
  }
  return primes;
}
vector<pair<long long int, long long int>> primeFactors(long long int n) {
  vector<long long int> primes = sieve(sqrt(n) + 2);
  long long int p;
  if (primes.size() > 0) {
    p = primes[0];
  } else {
    p = n + 1;
  }
  vector<pair<long long int, long long int>> f;
  int i = 0;
  while (i < primes.size() && p * p <= n) {
    long long int count = 0;
    while (p > 0 and n % p == 0) {
      count++;
      n /= p;
    }
    if (count > 0) {
      f.push_back(make_pair(p, count));
    }
    i++;
    p = primes[i];
  }
  if (n > 1) {
    f.push_back(make_pair(n, 1));
  }
  return f;
}
vector<long long int> factors(long long int n) {
  long long int lim = sqrt(n);
  vector<long long int> f;
  for (int i = 2; i <= lim; i++) {
    if (n % i == 0) {
      f.push_back(i);
      f.push_back(n / i);
    }
  }
  return f;
}
long long int ceilAB(long long int a, long long int b) {
  return (a + b - 1) / b;
}
long long int low_bound(vector<long long int>& v, long long int start,
                        long long int end, long long int n) {
  if (start > end) {
    return -1;
  }
  long long int mid = (start + end) / 2;
  if (v[mid] == n) {
    return mid;
  } else if (v[mid] > n) {
    long long int index = low_bound(v, start, mid - 1, n);
    return index;
  } else {
    long long int index = low_bound(v, mid + 1, end, n);
    if (index == -1) {
      return mid;
    }
    return index;
  }
}
void fastIO() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
}
unordered_map<pair<long long int, long long int>,
              pair<long long int, long long int>, myHash>
    dp;
pair<long long int, long long int> solve(vector<long long int>& v,
                                         long long int start, long long int n,
                                         long long int cur) {
  if (start == v.size()) {
    long long int x = -1;
    if (cur > n) {
      x = 1;
    }
    return make_pair(abs(n - cur), x);
  }
  if (dp.count(make_pair(start, cur)) > 0) {
    return dp[make_pair(start, cur)];
  }
  pair<long long int, long long int> op1 =
      solve(v, start + 1, n, cur * v[start]);
  pair<long long int, long long int> op2 = solve(v, start + 1, n, cur);
  pair<long long int, long long int> ans;
  if (op1.first < op2.first) {
    ans = op1;
  } else {
    ans = op2;
  }
  return dp[make_pair(start, cur)] = ans;
}
int main(void) {
  long long int n;
  cin >> n;
  vector<pair<long long int, long long int>> p = primeFactors(n);
  vector<long long int> v;
  for (int i = 0; i < p.size(); i++) {
    v.push_back(power(p[i].first, p[i].second));
  }
  pair<long long int, long long int> g = solve(v, 0, sqrt(n), 1);
  long long int a = sqrt(n) + g.first * g.second;
  long long int b = n / a;
  cout << min(a, b) << " " << max(a, b) << endl;
  return 0;
}
