// Slower C++ solution:
#include<cstdio>

#include<cstring>

#include<cmath>

#include<algorithm>

#include<iostream>

#include<queue>

#include<stack>

#include<vector>

#include<map>

#include<set>

#include<string>

#include<iomanip>

using namespace std;

#define eps 1e-12

#define INF 1000000

#define maxn 200005

double a[105][105];

double sum[105];

struct Edge

{

    int u,v;

    double w;

}b[10005],e[10005];

int pre[maxn],id[maxn],vis[maxn];

double in[maxn];



int dcmp(double x)

{

    if(fabs(x)<eps) return 0;

    return x<0?-1:1;

}



double Directed_MST(int root, int NV, int NE)

{

    double ret = 0;

    while(1)

    {

        for(int i=0;i<NV;i++)

            in[i]=INF;

        memset(pre,-1,sizeof(pre));

        memset(vis,-1,sizeof(vis));

        memset(id,-1,sizeof(id));

        for(int i=0;i<NE;i++)

        {

            if(e[i].u==e[i].v) continue;

            int v=e[i].v;

            if(dcmp(e[i].w-in[v])<0){

      //          ans=i;

                pre[v]=e[i].u;

                in[v]=e[i].w;

            }

        }

        for(int i=0;i<NV;i++)

        {

            if(dcmp(in[i]-INF)==0&&i!=root)

            {

                //cout<<i<<endl;

                return -1;

            }

        }

        int cnt=0;

        in[root]=0;

        for(int i=0;i<NV;i++)

        {

            ret+=in[i];

            int v=i;

            while(vis[v]!=i&&id[v]==-1&&v!=root)

            {

                vis[v]=i;

                v=pre[v];

            }

            if(v!=root&&id[v]==-1){

                for(int u=pre[v];u!=v;u=pre[u])

                {

                    id[u]=cnt;

                }

                id[v]=cnt++;

            }

        }

        if(cnt==0) break;

        for(int i=0;i<NV;i++)

            if(id[i]==-1) id[i]=cnt++;

        for(int i=0;i<NE;i++)

        {

            int v=e[i].v;

            e[i].u=id[e[i].u];

            e[i].v=id[e[i].v];

            e[i].w-=in[v];

        }

        NV = cnt;

        root = id[root];

     }

    return ret;

}

int main()

{

    int n,m;

    scanf("%d%d",&n,&m);

    for(int i=1;i<=m;i++)    for(int j=0;j<n;j++)    scanf("%lf",a[i]+j);

    int tot=0;

    for(int i=1;i<=m;i++)             //j->i??±?

    {

        for(int j=1;j<=m;j++)

        {

            double x1=0,x2=0,x3=0;     // y=r*r*x3-2*r*x2+x1

            for(int k=0;k<n;k++)

            {

                x1+=a[i][k]*a[i][k];

                x3+=a[j][k]*a[j][k];

                x2+=a[i][k]*a[j][k];

            }

            sum[i]=x1;

            if(i==j)    continue;

            double x=x2/x3;

            double y=x*x*x3-2.0*x*x2+x1;

            e[tot].u=j;

            e[tot].v=i;

            e[tot].w=y;

            tot++;

        }

    }

    for(int i=1;i<=m;i++)

    {

        e[tot].u=0;

        e[tot].v=i;

        e[tot].w=sum[i];

        tot++;

    }

    double temp=Directed_MST(0,m+1,tot);

    printf("%.7f\n",temp);

}

// Faster C++ solution for the same problem (measured speedup: 3.9585169095811095x):
#include<iostream>

#include<cstring>

#include<cstdio>

#include<cstdlib>

#include<cmath>

using namespace std;

const int maxn=110;

const int maxe=50010;

struct Edge

{

	int u,v;

	double w;

}edge[maxe];

int nv,ne;

void add(int u,int v,double w)

{

	edge[ne].u=u;

	edge[ne].v=v;

	edge[ne++].w=w;

}

const double inf=1e12;

double In[maxn];

int pre[maxn],ID[maxn],vis[maxn];

double Directed_MST(int root)

{

	double ret=0;

	int i,u,v,cnt;

	while(1)

	{

		for(i=0;i<=nv;++i)In[i]=inf;

		for(i=0;i<ne;++i)

		{

			u=edge[i].u;

			v=edge[i].v;

			if(edge[i].w<In[v]&&u!=v)

			{

				In[v]=edge[i].w;

				pre[v]=u;

			}

		}

		//cout <<"root:"<<root<<" ";for(i=0;i<=nv;++i)cout <<In[i]<<" ";cout <<endl;

		for(i=0;i<=nv;++i)

			if(i!=root&&In[i]==inf)return -1;

		cnt=0;

		memset(ID,-1,sizeof(ID));

		memset(vis,-1,sizeof(vis));

		In[root]=0;

		for(i=0;i<=nv;++i)

		{

			ret+=In[i];

			for(v=i;vis[v]!=i&&ID[v]==-1&&v!=root;v=pre[v])

				vis[v]=i;

			if(v!=root&&ID[v]==-1)

			{

				for(u=pre[v];u!=v;u=pre[u])

					ID[u]=cnt;

				ID[v]=cnt++;

			}

		}

		if(cnt==0)break;

		for(i=0;i<=nv;++i)

			if(ID[i]==-1)ID[i]=cnt++;

		for(i=0;i<ne;++i)

		{

			v=edge[i].v;

			edge[i].u=ID[edge[i].u];

			edge[i].v=ID[edge[i].v];

			if(edge[i].u!=edge[i].v)

				edge[i].w-=In[v];

		}

		nv=cnt-1;

		root=ID[root];

	}

	return ret;

}

int n,m;

#define sqr(v) ((v)*(v))

struct Point

{

	double v[101];

	double length()

	{

		double res=0;

		for(int i=0;i<m;++i)

			res+=sqr(v[i]);

		return res;

	}

	Point operator -(const Point &p)

	{

		Point res;

		for(int i=0;i<m;++i)

			res.v[i]=v[i]-p.v[i];

		return res;

	}

}pt[101];

double len(int a,int b)

{

	double lena=sqrt(pt[a].length()),lenb=sqrt(pt[b].length()),res=0;

	for(int i=0;i<m;++i)

		res+=pt[a].v[i]*pt[b].v[i];

	double cosv=res/lena/lenb;

	return sqr(lenb*sin(acos(cosv)));

}

int main()

{

	int i,j;

	scanf("%d%d",&m,&n);

	for(i=1;i<=n;++i)

	{

		for(j=0;j<m;++j)

		{

			scanf("%lf",&pt[i].v[j]);

		}

		add(0,i,pt[i].length());

	}

	for(i=1;i<=n;++i)

		for(j=1;j<=n;++j)

		{

			if(i==j)continue;

			add(i,j,len(i,j));

		}

	nv=n;

	printf("%.9f\n",Directed_MST(0));

	return 0;

}