#include <bits/stdc++.h>
using namespace std;
template <typename S, typename T>
ostream& operator<<(ostream& out, const pair<S, T> p) {
  out << "(" << p.first << "," << p.second << ")";
  return out;
}
template <typename T>
ostream& operator<<(ostream& out, const vector<T>& v) {
  for (auto a : v) out << a << " ";
  return out;
}
template <typename T>
ostream& operator<<(ostream& out, const set<T>& S) {
  for (auto a : S) cout << a << " ";
  return out;
}
template <typename T>
ostream& operator<<(ostream& out, const multiset<T>& S) {
  for (auto a : S) cout << a << " ";
  return out;
}
template <typename S, typename T>
ostream& operator<<(ostream& out, const map<S, T>& M) {
  for (auto m : M) cout << "(" << m.first << "->" << m.second << ") ";
  return out;
}
template <typename S, typename T>
pair<S, T> operator+(pair<S, T> a, pair<S, T> b) {
  return make_pair(a.first + b.first, a.second + b.second);
}
template <typename S, typename T>
pair<S, T> operator-(pair<S, T> a, pair<S, T> b) {
  return make_pair(a.first - b.first, a.second - b.second);
}
template <typename T>
struct ComplexGeometry {
  using point = complex<T>;
  vector<point> A;
  vector<int> sa;
  vector<int> tmp_sa;
  point smallest_enclosing_circle_center;
  T smallest_enclosing_circle_radius;
  vector<int> closest_pair_index;
  T inf = numeric_limits<T>::max();
  void init() { A.clear(); }
  void add_point(complex<T> a) { A.push_back(a); }
  void add_point(T x, T y) { A.emplace_back(x, y); }
  void remove_duplicate() {
    int n = A.size();
    auto cmp = [&](point a, point b) {
      if (a.real() != b.real()) return a.real() < b.real();
      return a.imag() < b.imag();
    };
    set<point, decltype(cmp)> S(cmp);
    for (int i = 0, j = 0; i < n; i++) {
      if (S.insert(A[i]).second) {
        A[j++] = A[i];
      }
      if (!S.count(A[i])) {
        A[j] = A[i];
        S.insert(A[i]);
      }
    }
    A.resize(S.size());
  }
  T static cross(point a, point b) { return (conj(a) * b).imag(); }
  T static cross(point a, point b, point c) { return cross(b - a, c - a); }
  T static dot(point a, point b) { return (conj(a) * b).real(); }
  point query_line_intersection(point a, point b, point p, point q) {
    double c1 = cross(p - a, b - a), c2 = cross(q - a, b - a);
    return (c1 * q - c2 * p) / (c1 - c2);
  }
  double query_line_point_perpendicular_distance(point s, point t, point a) {
    if (s == t) return abs(a - s);
    return abs(cross(s, t, a)) / abs(s - t);
  }
  point query_triangle_circumcenter(point a, point b, point c) {
    point d = (a + b) * polar<T>(0.5, 0.0);
    point e = d + (b - a) * polar<T>(1.0, acos(0.0));
    point f = (b + c) * polar<T>(0.5, 0.0);
    point g = f + (c - b) * polar<T>(1.0, acos(0.0));
    return query_line_intersection(d, e, f, g);
  }
  point query_triangle_circumcenter(const vector<point>& A) {
    if (A.size() != 3) return point(0.0, 0.0);
    return query_triangle_circumcenter(A[0], A[1], A[2]);
  }
  point query_triangle_incenter(vector<point>& A) {
    if (A.size() != 3) return point(0.0, 0.0);
    return query_triangle_incenter(A[0], A[1], A[2]);
  }
  point query_triangle_incenter(point a, point b, point c) {
    T A = abs(b - c);
    T B = abs(c - a);
    T C = abs(a - b);
    point p =
        a * polar<T>(A, 0.0) + b * polar<T>(B, 0.0) + c * polar<T>(C, 0.0);
    p = p / polar<T>(A + B + C, 0.0);
    return p;
  }
  T query_perimeter() { return query_polygon_perimeter(A); }
  T query_polygon_perimeter(const vector<point>& A) {
    int n = A.size();
    if (n <= 1) return 0;
    T ans = 0;
    for (int i = 0; i < n; i++) {
      int j = (i + 1) % n;
      ans += abs(A[i] - A[j]);
    }
    return ans;
  }
  T query_area() { return query_polygon_area(A); }
  point query_smallest_enclosing_circle_center() {
    return smallest_enclosing_circle_center;
  }
  T query_smallest_enclosing_circle_radius() {
    return smallest_enclosing_circle_radius;
  }
  void source_smallest_enclosing_circle() {
    point& circle_center = smallest_enclosing_circle_center;
    double& circle_radius = smallest_enclosing_circle_radius;
    circle_radius = inf;
    int n = A.size();
    if (n == 0) return;
    if (n == 1) {
      circle_center = A[0];
      circle_radius = 0;
      return;
    }
    double min_val = inf;
    double eps = 1e-6;
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
        point center = (A[i] + A[j]) * polar(0.5, 0.0);
        double radius = 0.5 * abs(A[i] - A[j]);
        int cnt = 0;
        for (int k = 0; k < n; k++) {
          if (abs(A[k] - center) <= radius + eps) {
            cnt++;
          }
        }
        if (cnt == n) {
          if (circle_radius > radius) {
            circle_radius = radius;
            circle_center = center;
          }
        }
      }
    }
    for (int i = 0; i < n; i++) {
      for (int j = i + 1; j < n; j++) {
        for (int k = j + 1; k < n; k++) {
          vector<double> B(3);
          B[0] = abs(A[i] - A[j]);
          B[1] = abs(A[j] - A[k]);
          B[2] = abs(A[k] - A[i]);
          sort(B.begin(), B.end());
          if (pow(B[2], 2) <= pow(B[0], 2) + pow(B[1], 2) + eps) {
            point center = query_triangle_circumcenter(A[i], A[j], A[k]);
            double radius = abs(center - A[i]);
            int cnt = 0;
            for (int l = 0; l < n; l++) {
              if (abs(A[l] - center) <= radius + 1e-6) {
                cnt++;
              }
            }
            if (cnt == n) {
              if (circle_radius > radius) {
                circle_radius = radius;
                circle_center = center;
              }
            }
          }
        }
      }
    }
  }
  T query_closest_pair_value() {
    auto B = query_closest_pair();
    if (B.empty()) return inf;
    return abs(B[0] - B[1]);
  }
  vector<int> query_closest_pair_index() { return closest_pair_index; }
  vector<point> query_closest_pair() {
    vector<point> ans;
    for (auto a : closest_pair_index) ans.push_back(A[a]);
    return ans;
  }
  T query_index_pair_dist(const vector<int>& sa) {
    if (sa.empty()) return inf;
    return abs(A[sa[0]] - A[sa[1]]);
  }
  T query_index_pair_dist(int a, int b) { return abs(A[a] - A[b]); }
  vector<int> divide_conquer_closest_pair(int left, int right) {
    if (left >= right) return vector<int>();
    if (left + 1 == right) {
      vector<int> v = {left, right};
      return v;
    }
    T min_val = inf;
    vector<int> min_sol;
    int mid = (left + right) / 2;
    auto left_sol = divide_conquer_closest_pair(left, mid);
    auto right_sol = divide_conquer_closest_pair(mid + 1, right);
    T left_val = query_index_pair_dist(left_sol);
    if (min_val > left_val) {
      min_val = left_val;
      min_sol = left_sol;
    }
    T right_val = query_index_pair_dist(right_sol);
    if (min_val > right_val) {
      min_val = right_val;
      min_sol = right_sol;
    }
    tmp_sa.clear();
    for (int i = left; i <= right; i++) {
      if (abs(A[sa[i]].real() - A[sa[mid]].real()) <= min_val) {
        tmp_sa.push_back(sa[i]);
      }
    }
    sort(tmp_sa.begin(), tmp_sa.end(),
         [&](int a, int b) { return A[a].imag() < A[b].imag(); });
    for (int i = 0; i < tmp_sa.size(); i++) {
      for (int j = i + 1; j < tmp_sa.size() && j <= i + 6; j++) {
        int s = tmp_sa[i];
        int t = tmp_sa[j];
        T cross_val = query_index_pair_dist(s, t);
        if (min_val > cross_val) {
          min_val = cross_val;
          min_sol = {s, t};
        }
      }
    }
    return min_sol;
  }
  void source_closest_pair() {
    int n = A.size();
    sa.resize(n);
    for (int i = 0; i < n; i++) sa[i] = i;
    sort(sa.begin(), sa.end(),
         [&](int a, int b) { return A[a].real() < A[b].real(); });
    closest_pair_index = divide_conquer_closest_pair(0, n - 1);
  }
  void dump_point() {
    int n = A.size();
    cout << __func__ << endl;
    cout << "n: " << n << endl;
    cout << "A: " << A << endl;
  }
  void dump_smallest_enclosing_circle() {
    cout << __func__ << endl;
    cout << "query_smallest_enclosing_circle_center: "
         << query_smallest_enclosing_circle_center() << endl;
    cout << "query_smallest_enclosing_circle_radius: "
         << query_smallest_enclosing_circle_radius() << endl;
  }
  void dump_closest_pair() {
    cout << __func__ << endl;
    cout << "query_closest_pair_index: " << query_closest_pair_index() << endl;
    cout << "query_closest_pair: " << query_closest_pair() << endl;
    cout << "query_closest_pair_value: " << query_closest_pair_value() << endl;
  }
  void dump() {
    cout << __func__ << endl;
    cout << "query_perimeter: " << query_perimeter() << endl;
    cout << "query_area: " << query_area() << endl;
    cout << "query_smallest_enclosing_circle_center: "
         << query_smallest_enclosing_circle_center() << endl;
    cout << "query_smallest_enclosing_circle_radius: "
         << query_smallest_enclosing_circle_radius() << endl;
  }
};
ComplexGeometry<long double> geometry;
using point = complex<long double>;
point solve(vector<point>& A) {
  int n = A.size();
  long double cnt = 0.0l;
  point ans(0.0L, 0.0);
  for (int i = 0; i < n; i++) {
    for (int j = i + 1; j < n; j++) {
      for (int k = j + 1; k < n; k++) {
        ans = ans + geometry.query_triangle_incenter(A[i], A[j], A[k]);
        cnt++;
      }
    }
  }
  ans = ans / polar<long double>(cnt, 0.0L);
  return ans;
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n, L;
  vector<point> A;
  cin >> n >> L;
  for (int i = 0; i < n; i++) {
    int a;
    cin >> a;
    A.push_back(polar<long double>(1.0L, 2 * acos(-1.0L) / L * a));
  }
  geometry.init();
  point ans = solve(A);
  cout << fixed << setprecision(15) << ans.real() << " " << ans.imag() << endl;
  return 0;
}
