#include <bits/stdc++.h>
int CH, NEG;
template <typename TP>
inline void read(TP& ret) {
  ret = NEG = 0;
  while (CH = getchar(), CH < '!')
    ;
  if (CH == '-') NEG = true, CH = getchar();
  while (ret = ret * 10 + CH - '0', CH = getchar(), CH > '!')
    ;
  if (NEG) ret = -ret;
}
int n;
namespace MaxClique {
using std::max;
inline int ctz(unsigned long long s) {
  return s ? __builtin_ctzll(s) : 8 * sizeof(unsigned long long);
}
int ans;
bool g[45LL][45LL];
unsigned long long N[45LL];
void dfs(unsigned long long R, unsigned long long P, unsigned long long X) {
  if (!P && !X) {
    ans = max(ans, __builtin_popcountll(R));
    return;
  }
  if (!P) return;
  int pivot = ctz(P | X);
  unsigned long long PP = P & ~N[pivot];
  for (int u = ctz(PP); u < n; u += ctz(PP >> (u + 1)) + 1) {
    dfs(R | ((unsigned long long)1 << u), P & N[u], X & N[u]);
    P ^= ((unsigned long long)1 << u), X |= ((unsigned long long)1 << u);
  }
}
int work() {
  int i, j;
  for (i = (0); i < (n); i++)
    for (j = (0); j < (n); j++)
      if (g[i][j]) N[i] ^= (unsigned long long)1 << j;
  dfs(0, ((unsigned long long)1 << n) - 1, 0);
  return ans;
}
}  // namespace MaxClique
int main() {
  int K, i, j;
  double ans;
  read(n), read(K);
  using MaxClique::g;
  using MaxClique::work;
  for (i = (0); i < (n); i++)
    for (j = (0); j < (n); j++) read(g[i][j]);
  i = work();
  ans = 1.0 * K * K * (i - 1) / i / 2.0;
  printf("%.12lf\n", ans);
END:
  getchar(), getchar();
  return 0;
}
