#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
#include<vector>
using namespace std;


struct edge
{
 int begin;int end;	
};

const int maxx=120;
bool vis[maxx],indfs[maxx];
vector<double>zero;
int n,m,root;
vector<vector<double> >vec;
double cost[maxx][maxx],Cost[maxx][maxx];
bool operator <(const edge a,const edge b)
{
 double ac=cost[a.begin][a.end];double bc=cost[b.begin][b.end];
 return ac>bc;//´?????´?????	
};
priority_queue<edge>que[maxx];
double minv(vector<double> a,vector<double> b)
{
 double ab=0,bsqrt=0,asqrt=0;
 for(int i=0;i<a.size();i++)
 	{ab+=a[i]*b[i];bsqrt+=b[i]*b[i];asqrt+=a[i]*a[i];}
 	
 if((bsqrt-0.0)<1e-10)return asqrt;
 return asqrt-(ab*ab/bsqrt);
}
int belongcircle[maxx];
int findbelong(int x)
{
 if(x==belongcircle[x])return x;
 	else return belongcircle[x]=findbelong(belongcircle[x]);
}

double ans,ansnow;
double min(double a,double b)
{
 if(a<b)return a;
 	else return b;
}
void combinecircle(int now,int begin)
{
 now=findbelong(now);
 if(vis[now])return ;
 vis[now]=true;
 edge e1=que[now].top();
 double coste=cost[findbelong(e1.begin)][findbelong(e1.end)];
 ansnow+=coste;
 bool finish[maxx];
 memset(finish,0,sizeof(finish));
 for(int i=0;i<=m;i++)
 	{
 	 int po=findbelong(i);
 	 if(po==now||po==begin)continue;
 	 if(finish[po])continue;
 	 finish[po]=true;
 	 cost[begin][po]=min(cost[begin][po],cost[now][po]-coste);
 	 cost[po][begin]=min(cost[po][begin],cost[po][now]);
	}
 belongcircle[now]=begin;
 combinecircle(e1.end,begin);
 return ;
}
void build();
bool findcircle(int now)
{
 if(now==root)return false; 
 now=findbelong(now);
 if(indfs[now])
 	{
 	 memset(vis,0,sizeof(vis));
 	 combinecircle(now,now);
 	 build();
 	 return true;
	}
 indfs[now]=true;
 return findcircle(que[now].top().end);
}

void build()
{
 bool finish[maxx];
 memset(finish,0,sizeof(finish));
 for(int i=0;i<m;i++)
 	{
 	 int po=findbelong(i);
 	 if(finish[po])continue;
 	 finish[po]=true;
 	 while(!que[po].empty())que[po].pop();
 	 for(int j=0;j<=m;j++)
 	 	{
 	 	 int pb=findbelong(j);
 	 	 if(po==pb)continue;
 	 	 edge en;en.begin=po;en.end=pb;
 	 	 que[po].push(en);
		}
	}
 return ;
}
bool counted[maxx];
int main()
{
 ios::sync_with_stdio(false);
 cin>>n>>m;
 for(int i=0;i<n;i++)
    zero.push_back(0.0);
 for(int i=0;i<m;i++)
 	{
	 vector<double>nowv;
	 for(int j=0;j<n;j++)
	 	{ double nv;cin>>nv;nowv.push_back(nv);}
	 vec.push_back(nowv);
	}
 vec.push_back(zero);
 for(int i=0;i<=m;i++)
 	for(int j=0;j<=m;j++)
 		{ cost[i][j]=minv(vec[i],vec[j]);}
 root=m;
 ansnow=0;
 belongcircle[root]=root;
 	 for(int i=0;i<m;i++)
 	 	{
 	 	 belongcircle[i]=i;
 	 	}
	 bool exis=false;
	 	 do
	 	 	{
	 	 	 build();
	 	 	 exis=false;
	 	 	 bool finish[maxx];
	 	 	 memset(finish,0,sizeof(finish));
	 	 	 for(int i=0;i<m;i++)
	 	 	 {  
			    int po=findbelong(i);
			    if(finish[po])continue;
	 	 	    memset(indfs,0,sizeof(indfs));
	 	 	    exis=findcircle(po);
	 	 	    finish[po]=true;
			 }
			}while(exis);
	 memset(counted,0,sizeof(counted));
	 for(int i=0;i<m;i++)
	 	{
		 int po=findbelong(i);
		 if(counted[po])continue;
		 counted[po]=true;
		 ansnow+=cost[findbelong(que[po].top().begin)][findbelong(que[po].top().end)];	
		}
 printf("%.8f\n",ansnow);
 return 0;
}