// 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.97485843913093x):
#include<iostream>

#include<cstring>

#include<cstdio>

#include<algorithm>

#include<cmath>

#include<stack>

#include<queue>

#include<vector>

#include<map>

#include<ctime>

using namespace std;

#define LL double

#define rep(i, n) for (int i = 0; i < (n); ++i)

#define sqr(x) (x)*(x)

const int MAX=1005;

const LL inf=1e30;

struct node

{

    int u,v;

    LL w;

}g[MAX*MAX];

int e,ans;

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

LL in[MAX],sum,res,gg[105][105];

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

{

    g[e].u=u; g[e].v=v; g[e++].w=w;

    //cout<<u<<"->"<<v<<" "<<w<<endl;

    gg[u][v]=w;

}

double ZL(int root,int n)

{

    int i,j,k,u,v,vn;

    res=0;

    while(1)

    {

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

            in[i]=inf;

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

        {

            u=g[i].u; v=g[i].v;

            if(g[i].w<in[v]&&u!=v)

            {

                pre[v]=u;

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

            }

        }

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

        {

            if(i!=root&&in[i]==inf)

                return false;

        }

        vn=0;

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

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

        in[root]=0;

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

        {

            res+=in[i];

            v=i;

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

            {

                vis[v]=i;

                v=pre[v];

            }

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

            {

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

                {

                    id[u]=vn;

                }

                id[v]=vn++;

            }

        }

        if(vn==0)

            break;

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

        {

            if(id[i]==-1)

                id[i]=vn++;

        }

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

        {

            v=g[i].v;

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

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

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

            {

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

            }

        }

        n=vn;

        root=id[root];

    }

    return res;

}

double a[105][105],len[105];

int main()

{

    int n,m,i,j,k;

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

    {

        e=0;

        rep (i, m) {

            len[i] = 0;

            rep (j, n) {

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

                len[i] += a[i][j] * a[i][j];

            }

            len[i] = sqrt(len[i]);

        }

        rep (i, m) {

            rep (j, m) {

                if (i == j) continue;

                double now = 0.0;

                rep (k, n) {

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

                }

                now /= len[i] * len[j];

                now = sqrt (1.0 - now * now);

                gg[j + 1][i + 1] = sqr(len[i] * now);

                add(j+1,i+1,gg[j+1][i+1]);

            }

            gg[0][i + 1] = sqr(len[i]);

            add(0,i+1,gg[0][i+1]);

            //gg[i + 1][0] = -1;

            //gg[i + 1][i + 1] = -1;

        }

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

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

                //printf("%d->%d %lf\n",i,j,gg[i][j]);

        printf("%.8f\n",ZL(0,m+1));

    }

    return 0;

}