#include <bits/stdc++.h>
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("fast-math")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("O3")
using namespace std;
const long long INF = 1e18;
struct node {
  long long x;
  node() {}
  node(long long x1) { x = x1; }
};
struct segment_tree {
  vector<node> tree;
  long long n;
  node e;
  node operation(node a, node b) { return node(max(a.x, b.x)); }
  node get_e() { return 0; }
  void build(vector<long long> &a, long long v, long long l, long long r) {
    if (l + 1 == r) {
      tree[v] = node(a[l]);
      return;
    }
    long long m = (l + r) / 2;
    build(a, 2 * v + 1, l, m);
    build(a, 2 * v + 2, m, r);
    tree[v] = operation(tree[2 * v + 1], tree[2 * v + 2]);
  }
  segment_tree() { e = get_e(); }
  segment_tree(long long n1) {
    n = n1;
    tree.assign(4 * n, 0);
    e = get_e();
  }
  segment_tree(vector<long long> &a) {
    n = a.size();
    tree.assign(4 * n, node(0));
    e = get_e();
    build(a, 0, 0, n);
  }
  void local_update(long long v, long long l, long long r, long long qi,
                    long long qx) {
    if (l + 1 == r) {
      tree[v] = qx;
      return;
    }
    long long m = (l + r) / 2;
    if (qi < m)
      local_update(2 * v + 1, l, m, qi, qx);
    else
      local_update(2 * v + 2, m, r, qi, qx);
    tree[v] = operation(tree[2 * v + 1], tree[2 * v + 2]);
  }
  void update(long long i, long long x) { local_update(0, 0, n, i, x); }
  node local_get_ans(long long v, long long l, long long r, long long ql,
                     long long qr) {
    if (ql <= l && r <= qr) {
      return tree[v];
    }
    if (r <= ql || qr <= l) {
      return e;
    }
    long long m = (l + r) / 2;
    node t1 = local_get_ans(2 * v + 1, l, m, ql, qr);
    node t2 = local_get_ans(2 * v + 2, m, r, ql, qr);
    return operation(t1, t2);
  }
  long long get_ans(long long l, long long r) {
    node ans = local_get_ans(0, 0, n, l, r);
    return ans.x;
  }
};
signed main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  long long n;
  cin >> n;
  vector<pair<long long, long long>> a(n);
  for (long long i = 0; i < n; ++i) {
    long long r, t;
    cin >> r >> t;
    a[i] = {r * r * t, i};
  }
  sort(a.begin(), a.end());
  vector<pair<long long, long long>> vec(n);
  long long t = 0;
  for (long long i = 0; i < n; ++i) {
    if (a[i].first != a[t].first) t = i;
    vec[a[i].second] = {i, t};
  }
  vector<long long> dp(n, 0);
  segment_tree seg(dp);
  for (long long i = 0; i < n; ++i) {
    long long o = seg.get_ans(0, vec[i].second);
    dp[i] = o + a[vec[i].first].first;
    seg.update(vec[i].first, dp[i]);
  }
  long long ans = 0;
  for (auto it : dp) ans = max(ans, it);
  cout << fixed << setprecision(10);
  cout << (long double)ans * (long double)acos(-1);
}
