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

#include <cctype>

#include <cstring>

#include <cstdio>

#include <cmath>

#include <algorithm>

#include <vector>

#include <string>

#include <iostream>

#include <sstream>

#include <map>

#include <set>

#include <queue>

#include <stack>

#include <ctime>

using namespace std;

typedef long long ll;

#define clr(x,a) memset(x,a,sizeof(x))

#define sz(x) (int)x.size()

#define see(x) cerr<<#x<<" "<<x<<endl

#define se(x) cerr<<" "<<x 

#define pb push_back

#define mk make_pair

#define X first

#define Y second

#define maxn 205

#define maxm 11005

#define type double 

double sqr(double x)

{

	return x*x;

}

const int inf = ~0u >> 1;

struct edge

{

    int u,v;

    type cost;

    int oldu,oldv;

    edge(){}

    edge(int a,int b,type c,int d,int e):u(a),v(b),cost(c),oldu(d),oldv(e){}

}e[maxm];

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

int mark;

type in[maxn];

type dirmst(int root,int nv,int ne)

{

    type ret = 0;

    int cnt = 0;

    int oldroot = root;

    while(1)

    {

        cnt++;

        fill(in,in + nv,inf);

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

        {

            int u = e[i].u;

            int v = e[i].v;

            if(e[i].cost < in[v] && u != v)

            {

                if(e[i].oldu == oldroot)

                    mark = e[i].oldv;

                pre[v] = u;

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

            }

        }

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

        {

            if(i == root)

                continue;

            if(in[i] == inf)

                return -1;

        }

        int cntnode = 0;

        fill(id,id + nv,-1);

        fill(vis,vis + nv,-1);

        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] = cntnode;

                id[v] = cntnode++;

            }

        }

        if(cntnode == 0)

            break;

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

            if(id[i] == -1)

                id[i] = cntnode++;

        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];

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

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

        }

        nv = cntnode;

        root = id[root];

    }

    return ret;

}



int n,m;

double dv[maxn],db[maxn][maxn];

double g[maxn][maxn],f[maxn][maxn];

void init()

{

	int i,j,k;

	clr(g,0);

	clr(dv,0);

	clr(db,0);

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

	{

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

		{

			scanf("%lf",&g[i][j]);

			dv[i]+=sqr(g[i][j]);

		}

	}

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

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

	{

		for(k=1; k<=m; k++)

		{

			db[i][j]+=g[i][k]*g[j][k];

		}

	}

}



int main()

{

	//freopen("in","r",stdin);

	int i,j,k;

    while(scanf("%d %d",&m,&n) == 2)

    {

    	init();

        int sum = 0;

        mark = -1;

        int el=0;

        clr(f,0);

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

        {

        	j=0;

        	f[j][i]=dv[i];

        	e[el++] = edge(j,i,f[j][i],j,i);

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

        	if(i!=j)

        	{

        		f[j][i]=(dv[j]*dv[i]-db[i][j]*db[i][j])/dv[j];

        		e[el++] = edge(j,i,f[j][i],j,i);

        	}

        }

		

        double ans = dirmst(0,n + 1,el);

        printf("%.6f\n",ans);

    }

}

// Faster C++ solution for the same problem (measured speedup: 1.981041090542225x):
#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;

}