#include <bits/stdc++.h>
#include <boost/math/constants/constants.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>

template<class RandomAccessIterator, class Field>
RandomAccessIterator fast_fourier_transform(RandomAccessIterator first, RandomAccessIterator last, RandomAccessIterator result, Field hint){
    ::std::vector<Field> res(first, last);
    ::std::size_t N = res.size();

    // bit reverse
    for(::std::size_t i = 0, j = 0; i < N; ++i){
        if(i < j)::std::swap(res[i], res[j]);
        j ^= N / (1 + (i ^ (i + 1))) * (i ^ (i + 1));
    }

    ::std::stack<Field> root;
    root.push(hint);
    for(::std::size_t i = 2; i < N; i <<= 1){
        root.push(hint *= hint);
    }

    // fft
    for(::std::size_t i = 1; i < N; i <<= 1){
        auto t = root.top();
        root.pop();
        for(::std::size_t j = 0; j < N; j += 2 * i){
            Field coef = static_cast<Field>(1);
            for(::std::size_t k = 0; k < i; ++k){
                auto tmp = res[j + k];
                res[j + k] += coef * res[j + k + i];
                res[j + k + i] = tmp - coef * res[j + k + i];
                coef *= t;
            }
        }
    }

    return ::std::copy(res.begin(), res.end(), result);

}

using real = boost::multiprecision::cpp_dec_float_100;

real pi = boost::math::constants::pi<real>();
::std::size_t t = 1;

template<class RandomAccessIterator1, class RandomAccessIterator2, class RandomAccessIterator3>
RandomAccessIterator1 convolution(RandomAccessIterator1 first1, RandomAccessIterator1 last1, RandomAccessIterator2 first2, RandomAccessIterator2 last2, RandomAccessIterator3 result){
    using value_type = typename ::std::iterator_traits<RandomAccessIterator1>::value_type;
    using size_type = ::std::size_t;
    size_type N = last1 - first1, M = last2 - first2;
    while(t < N + M)t <<= 1;

    ::std::vector<value_type> input1(first1, last1), input2(first2, last2), chukan1(t), chukan2(t), res(t);
    input1.resize(t);
    input2.resize(t);
    value_type hint = value_type(::boost::multiprecision::cos(pi / (t / 2)), ::boost::multiprecision::sin(pi / (t / 2))), ihint = value_type(::boost::multiprecision::cos(pi / (t / 2)), -::boost::multiprecision::sin(pi / (t / 2)));
    fast_fourier_transform(input1.begin(), input1.end(), chukan1.begin(), hint);
    fast_fourier_transform(input2.begin(), input2.end(), chukan2.begin(), hint);
    ::std::transform(chukan1.begin(), chukan1.end(), chukan2.begin(), res.begin(), ::std::multiplies<value_type>());

    return fast_fourier_transform(res.begin(), res.end(), result, ihint);
}

int main(){
    using real = boost::multiprecision::cpp_dec_float_100;
    using namespace std;
    unsigned long N, L;
    cin >> N >> L;
    vector<unsigned long> T(N);
    copy_n(istream_iterator<unsigned long>(cin), N, T.begin());
    vector<complex<real>> ps(N), res(4 * N);
    transform(T.begin(), T.end(), ps.begin(), [&L](auto t){return complex<real>(cos(pi * t / L), sin(pi * t / L));});
    convolution(ps.begin(), ps.end(), ps.rbegin(), ps.rend(), res.begin());
    complex<real> x{0};
    for(long i = 0, c = -N; i + 1 < N; ++i){
        x += res[i] * static_cast<real>(c += 2);
    }
    t *= N * (N - 1) * (N - 2) / 6;
    x /= t;
    cout << x.real().str(50, std::ios_base::fixed) << " " << x.imag().str(50, std::ios_base::fixed) << endl;
    return 0;
}

Measured memory_bytes: 10320