#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;
 
#define fi first
#define se second
#define mp make_pair
#define pb push_back
 
typedef long long ll;
typedef pair<ll,ll> ii;
typedef vector<int> vi;
typedef unsigned long long ull;
typedef double ld; 
typedef tree<ii, null_type, less<ii>, rb_tree_tag, tree_order_statistics_node_update> pbds;
int a[3333];

ll nc3(ll n)
{
	return ((n*(n-1)*(n-2)))/6;
}

ll n,L; 

const ld eps=1e-12;
const ld pi=acos(-1.0);
const ld inf=1e20;
const int maxp=111111;
int dblcmp(ld d)
{
    if (fabs(d)<eps)return 0;
    return d>eps?1:-1;
}
inline ld sqr(ld x){return x*x;}
struct point 
{
    ld x,y;
    point(){}
    point(ld _x,ld _y):
    x(_x),y(_y){};
    void input()
    {
        scanf("%lf%lf",&x,&y);
    }
    void output()
    {
        printf("%.2f %.2f\n",x,y);
    }
    bool operator==(point a)const
    {
        return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0;
    }
    bool operator<(point a)const
    {
        return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x;
    }
    ld len()
    {
        return hypot(x,y);
    }
    ld len2()
    {
        return x*x+y*y;
    }
    ld distance(point p)
    {
        return hypot(x-p.x,y-p.y);
    }
    point add(point p)
    {
        return point(x+p.x,y+p.y);
    }
    point sub(point p)
    {
        return point(x-p.x,y-p.y);
    }
    point mul(ld b)
    {
        return point(x*b,y*b);
    }
    point div(ld b)
    {
        return point(x/b,y/b);
    }
    ld dot(point p)
    {
        return x*p.x+y*p.y;
    }
    ld det(point p)
    {
        return x*p.y-y*p.x;
    }
    ld rad(point a,point b)
    {
        point p=*this;
        return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
    }
    point trunc(ld r)
    {
        ld l=len();
        if (!dblcmp(l))return *this;
        r/=l;
        return point(x*r,y*r);
    }
    point rotleft()
    {
        return point(-y,x);
    }
    point rotright()
    {
        return point(y,-x);
    }
    point rotate(point p,ld angle)//绕点p逆时针旋转angle角度 
    {
        point v=this->sub(p);
        ld c=cos(angle),s=sin(angle);
        return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
    }        
};

const ld PI = acos(-1);

point F(ll a, ll N)
{
	return {cos(2*PI*ld(a)/ld(N)),sin(2*PI*ld(a)/ld(N))};
}
int main()
{
	ios_base::sync_with_stdio(0); cin.tie(0);
	cin>>n>>L; L*=2;
	for(int i=0;i<n;i++)
	{
		cin>>a[i]; a[i]*=2;
	}
	ld ans[2]={0,0};
	for(int i=0;i<n;i++)
	{
		vector<point> sum(n+1,point(0,0));
		ll l=a[i];
		for(int j=i+1;j<n;j++)
		{
			sum[j]=sum[j-1];
			point tp = F(a[j]-l,2*L);
			sum[j].x+=tp.x; sum[j].y+=tp.y;
		}
		for(int j=i+2;j<n;j++)
		{
			ll r=a[j];
			ll m=(r+l+L)/2;
			//<<m<<'\n';
			ll cnt=j-i-1;
			ld tmp[2]={sum[j-1].x-sum[i].x,sum[j-1].y-sum[i].y};
			/*for(int k=i+1;k<j;k++)
			{
				point pt = F(a[k]-l,2*L);
				//<<a[k]-l<<' '<<2*L<<'\n';
				tmp[0]+=pt.x; tmp[1]+=pt.y;
			}*/
			tmp[0]/=cnt; tmp[1]/=cnt;
			//centre of gravity in tmp
			point cent = F(m,L);
			point lpt = F(l,L);
			point newpt; newpt.x=tmp[0]; newpt.y=tmp[1];
			point disp; disp.x = lpt.x-cent.x; disp.y=lpt.y-cent.y;
			////<<disp.x<<' '<<disp.y<<' '<<disp.y/disp.x<<' '<<atan2(disp.x,disp.y)*180/PI<<'\n';
			//<<"ANGLE ROT: "<<atan2(disp.y,disp.x)<<'\n';
			newpt=newpt.rotate(point(0,0),atan2(disp.y,disp.x));
			tmp[0]=newpt.x; tmp[1]=newpt.y;
			ld R = F(l,L).distance(F(m,L));
			//<<tmp[0]<<' '<<tmp[1]<<' '<<cent.x<<' '<<cent.y<<' '<<R<<'\n';
			tmp[0]*=R; tmp[1]*=R;		
			tmp[0]+=cent.x;
			tmp[1]+=cent.y;
			tmp[0]*=cnt; tmp[1]*=cnt;
			//<<tmp[0]<<' '<<tmp[1]<<' '<<cent.x<<' '<<cent.y<<' '<<R<<'\n';
			ans[0]+=tmp[0];ans[1]+=tmp[1];
		}
	}
	ans[0]/=ld(nc3(n));
	ans[1]/=ld(nc3(n));
	cout<<fixed<<setprecision(15)<<ans[0]<<' '<<ans[1]<<'\n';
}


Measured memory_bytes: 768