Problem: As you know, every birthday party has a cake! This time, Babaei is going to prepare the very special birthday party's cake.

Simple cake is a cylinder of some radius and height. The volume of the simple cake is equal to the volume of corresponding cylinder. Babaei has n simple cakes and he is going to make a special cake placing some cylinders on each other.

However, there are some additional culinary restrictions. The cakes are numbered in such a way that the cake number i can be placed only on the table or on some cake number j where j < i. Moreover, in order to impress friends Babaei will put the cake i on top of the cake j only if the volume of the cake i is strictly greater than the volume of the cake j.

Babaei wants to prepare a birthday cake that has a maximum possible total volume. Help him find this value.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of simple cakes Babaei has.

Each of the following n lines contains two integers ri and hi (1 ≤ ri, hi ≤ 10 000), giving the radius and height of the i-th cake.

Output

Print the maximum volume of the cake that Babaei can make. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.

Namely: let's assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if <image>.

Examples

Input

2
100 30
40 10


Output

942477.796077000


Input

4
1 1
9 7
1 4
10 7


Output

3983.539484752

Note

In first sample, the optimal way is to choose the cake number 1.

In second sample, the way to get the maximum volume is to use cakes with indices 1, 2 and 4.

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
template <class T>
T max(T a, T b, T c) {
  return max(a, max(b, c));
}
template <class T>
T min(T a, T b, T c) {
  return min(a, min(b, c));
}
void fastio() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
}
bool prime[10000005];
void SieveOfEratosthenes(long long int n) {
  memset(prime, true, sizeof(prime));
  for (long long int p = 2; p * p <= n; p++) {
    if (prime[p] == true) {
      for (long long int i = p * p; i <= n; i += p) prime[i] = false;
    }
  }
}
bool isPrime(long long int n) {
  if (n < 2) return false;
  for (long long int i = 2; i * i <= n; i++)
    if (n % i == 0) return false;
  return true;
}
std::vector<long long int> generatePrimeFactors(long long int n) {
  std::vector<long long int> prime;
  for (long long int i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      prime.push_back(i);
      while (n % i == 0) n = n / i;
    }
  }
  if (n != 1) prime.push_back(n);
  return prime;
}
std::vector<long long int> generateFactors(long long int n) {
  std::vector<long long int> fact;
  for (long long int i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      fact.push_back(i);
      if (n / i != i) fact.push_back(n / i);
    }
  }
  fact.push_back(1);
  if (n != 1) fact.push_back(n);
  sort(fact.begin(), fact.end());
  return fact;
}
long long int extendedGCD(long long int a, long long int b, long long int &x,
                          long long int &y) {
  if (a == 0) {
    x = 0;
    y = 1;
    return b;
  }
  long long int x1, y1, d;
  d = extendedGCD(b % a, a, x1, y1);
  x = y1 - (b / a) * x1;
  y = x1;
  return d;
}
long long int gcd(long long int a, long long int b) {
  while (b) {
    a %= b;
    swap(a, b);
  }
  return a;
}
long long int multiply(long long int a, long long int b, long long int m);
long long int singlemod(long long int a, long long int m);
long long int modpow(long long int x, long long int n, long long int m) {
  if (n == 0) return 1;
  long long int res = 1;
  while (n) {
    if (n % 2) res = multiply(res, x, m);
    x = multiply(x, x, m);
    n = n >> 1;
  }
  return singlemod(res, m);
}
long long int modinverse(long long int x, long long int m) {
  return modpow(x, m - 2, m);
}
long long int add(long long int a, long long int b, long long int m) {
  return (((a % m) + (b % m)) % m);
}
long long int substract(long long int a, long long int b, long long int m) {
  if (a < b) swap(a, b);
  return (((a % m) - (b % m) + m) % m);
}
long long int multiply(long long int a, long long int b, long long int m) {
  return (((a % m) * (b % m)) % m);
}
long long int divide(long long int a, long long int b, long long int m) {
  long long int temp = modinverse(b, m);
  return multiply(a, temp, m);
}
long long int singlemod(long long int a, long long int m) { return (a % m); }
long long int eulerstotientfunction(long long int n) {
  long long int ans = n;
  for (long long int i = 2; i * i <= n; i++) {
    if (n % i == 0) {
      while (n % i == 0) n = n / i;
      ans -= ans / i;
    }
  }
  if (n > 1) ans -= ans / n;
  return ans;
}
long long int ncr(long long int n, long long int k, long long int m) {
  if (k > n) return 0;
  long long int res = 1;
  k = min(k, n - k);
  for (long long int i = 1; i <= k; i++) {
    res = multiply(res, n - i + 1, m);
    res = divide(res, i, m);
  }
  return singlemod(res, m);
}
long long int kadaneAlgo(const std::vector<long long int> &arr) {
  long long int size = arr.size();
  long long int currmax = arr[0], maxsofar = arr[0];
  for (long long int i = 1; i < size; i++) {
    currmax = max(arr[i], currmax + arr[i]);
    maxsofar = max(maxsofar, currmax);
  }
  return maxsofar;
}
long long int getDigitSum(long long int n) {
  long long int co = 0;
  while (n > 0) {
    co += n % 10;
    n = n / 10;
  }
  return co;
}
template <class T>
void printVector(const std::vector<T> arr) {
  for (auto i : arr) cout << i << " ";
  cout << '\n';
}
template <class T>
void printArray(T arr[], long long int n) {
  for (long long int i = 0; i < n; i++) cout << arr[i] << " ";
  cout << '\n';
}
long long int seg_tree[4 * 100005], arr[100005];
void build(long long int index, long long int start, long long int end) {
  if (start > end) return;
  if (start == end) {
    seg_tree[index] = arr[start];
    return;
  }
  long long int mid = start + (end - start) / 2;
  build(2 * index + 1, start, mid);
  build(2 * index + 2, mid + 1, end);
  seg_tree[index] = max(seg_tree[2 * index + 1], seg_tree[2 * index + 2]);
  return;
}
long long int query(long long int index, long long int start, long long int end,
                    long long int qstart, long long int qend) {
  if (start > end || start > qend || end < qstart) return 0;
  if (start >= qstart && end <= qend) {
    return seg_tree[index];
  }
  long long int mid = start + (end - start) / 2;
  return max(query(2 * index + 1, start, mid, qstart, qend),
             query(2 * index + 2, mid + 1, end, qstart, qend));
}
void update(long long int index, long long int start, long long int end,
            long long int pos, long long int val) {
  if (start > end) return;
  if (start == end && start == pos) {
    seg_tree[index] = max(val, seg_tree[index]);
    return;
  }
  long long int mid = start + (end - start) / 2;
  if (pos <= mid)
    update(2 * index + 1, start, mid, pos, val);
  else
    update(2 * index + 2, mid + 1, end, pos, val);
  seg_tree[index] = max(seg_tree[2 * index + 1], seg_tree[2 * index + 2]);
}
bool cmp(pair<long long int, long long int> A,
         pair<long long int, long long int> B) {
  if (A.first == B.first) return A.second > B.second;
  return A.first < B.first;
}
int main() {
  fastio();
  long long int t = 1;
  while (t--) {
    long long int n;
    cin >> n;
    std::vector<pair<long long int, long long int> > arr(n), temp(n);
    for (long long int i = 0; i < n; i++) {
      cin >> arr[i].first >> arr[i].second;
      temp[i].first = arr[i].first * arr[i].first * arr[i].second;
      temp[i].second = i;
    }
    sort(temp.begin(), temp.end(), cmp);
    std::vector<char> v;
    long long int dp[n];
    fill(dp, dp + n, 0);
    for (long long int i = 0; i < n; i++) {
      dp[i] = temp[i].first + query(0, 0, n - 1, 0, temp[i].second - 1);
      update(0, 0, n - 1, temp[i].second, dp[i]);
    }
    cout << fixed << setprecision(9)
         << *max_element(dp, dp + n) * 1.0 * 3.14159265358979323846 << '\n';
  }
}