#include <bits/stdc++.h>
using namespace std;
const int N = 100 + 10;
const int M = 10000 + 10;
struct edge
{
    int u, v;
    double cost;
    edge() {}
    edge(int u, int v, double c): u(u), v(v), cost(c) {}
} e[M];
int pre[N], hash1[N], vis[N];
double In[N];
double Directed_MST(int root, int n, int m)
{
    double ret = 0;
    while(true)
    {
        for(int i = 0; i < n; i++)
            In[i] = INT_MAX;
        for(int i = 0; i < m; i++) //找最小入?
        {
            int u = e[i].u;
            int v = e[i].v;
            if(e[i].cost < In[v] && u != v)
            {
                pre[v] = u;
                In[v] = e[i].cost;
            }
        }
        for(int i = 0; i < n; i++)
        {
            if(i == root)
                continue;
            if(In[i] == INT_MAX)
                return -1;
        }
        int cntnode = 0;
        memset(hash1, -1, sizeof(hash1));
        memset(vis, -1, sizeof(vis));
        In[root] = 0;
        for(int i = 0; i < n; i++) //找?
        {
            ret += In[i];
            int v = i;
            while(vis[v] != i && hash1[v] == -1 && v != root)
            {
                vis[v] = i;
                v = pre[v];
            }
            if(v != root && hash1[v] == -1)
            {
                for(int u = pre[v]; u != v; u = pre[u])
                    hash1[u] = cntnode;
                hash1[v] = cntnode++;
            }
        }
        if(cntnode == 0)
            break;
        for(int i = 0; i < n; i++)
            if(hash1[i] == -1)
                hash1[i] = cntnode++;
        for(int i = 0; i < m; i++) //重??
        {
            int v = e[i].v;
            e[i].u = hash1[e[i].u];
            e[i].v = hash1[e[i].v];
            if(e[i].u != e[i].v)
                e[i].cost -= In[v];
        }
        n = cntnode;
        root = hash1[root];
    }
    return ret;
}
int n, m;
const int MAXV = 100 + 10;
double vc[MAXV][MAXV];
double A, B, C;
inline double calCost(double r)
{
    return A - r * B + r * r * C;
}
const double EPS = 1e-10;
inline int sgn(double x) {return x < -EPS ? -1 : x > EPS ? 1 : 0;}
int main()
{
#ifdef ACM_TEST
    freopen("in.txt", "r", stdin);
//	freopen("in.txt", "w", stdout);
#endif
    scanf("%d%d", &m, &n);
    for(int i = 1; i <= n; ++i)
        for(int j = 0; j < m; ++j)
            scanf("%lf", &vc[i][j]);
    int tot = 0;
    for(int i = 1; i <= n; ++i)
    {
        double val = 0.0;
        for(int j = 0; j < m; ++j)
            val += vc[i][j] * vc[i][j];
        e[tot++] = edge(0, i, val);
    }
    for(int i = 1; i <= n; ++i)
        for(int j = 1; j <= n; ++j)
        {
            if(i == j) continue;
            A = 0, B = 0, C = 0;
            for(int k = 0; k < m; ++k)
            {
                A += vc[i][k] * vc[i][k];
                B += 2.0 * vc[i][k] * vc[j][k];
                C += vc[j][k] * vc[j][k];
            }
            double l = -1e8, r = 1e8, ll, rr;
            for(int k = 0; k < 100; ++k)
            {
                ll = (l + l + r) / 3.0;
                rr = (l + r + r) / 3.0;
                if(sgn(calCost(ll) - calCost(rr)) >= 0) l = ll;
                else r = rr;
            }
            e[tot++] = edge(j, i, calCost(l));
        }
    double ans = Directed_MST(0, n + 1, tot);
    printf("%.10f\n", ans);
    return 0;
}

Measured memory_bytes: 1488