#include <bits/stdc++.h>
using namespace std;
int g[4][2] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
char s[2048][4096];
int n, m, block[16384];
vector<int> adj[16384];
struct QUE {
  int h, b, q[500000];
  inline void init() { b = h = 0; }
  inline void push(int x) {
    if (rand() % 2)
      q[b++] = x, (b == 500000) && (b = 0);
    else
      h ? (--h) : (h = 500000 - 1), q[h] = x;
    if (h == b) exit(0);
  }
  inline int front() { return q[h]; }
  inline void pop() { ((++h) == 500000) && (h = 0); }
  inline bool empty() { return h == b; }
} q;
inline void GET(char &c) {
  for (c = getchar(); !((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'));
       c = getchar())
    ;
  if (c >= '0' && c <= '9')
    c -= '0';
  else
    c -= 'A' - 10;
}
int main() {
  srand(time(NULL));
  int i, j, k, x, y, z, a, b, t, clr, ans = 0;
  scanf("%d %d", &n, &m);
  for (i = 0; i < n && i < 2048; ++i)
    for (j = (m >> 2) - 1; ~j; --j) GET(s[i][j]);
  for (j = 0, clr = 0, t = i - 1; j < m; ++j) {
    if (((s[t][j >> 2] >> (j & 3)) & 1) == 0) continue;
    (s[t][j >> 2] ^= (1 << (j & 3)));
    block[j] = ++clr;
    ++ans;
    for (q.init(), q.push((t << 14) + j); !q.empty();) {
      k = q.front();
      q.pop();
      a = k >> 14;
      b = k & 16383;
      if (a == t) block[b] = clr, adj[clr].push_back(b);
      for (z = 0; z < 4; ++z) {
        x = a + g[z][0];
        y = b + g[z][1];
        if (x < 0 || x >= i || y < 0 || y >= m ||
            ((s[x][y >> 2] >> (y & 3)) & 1) == 0)
          continue;
        (s[x][y >> 2] ^= (1 << (y & 3)));
        q.push((x << 14) + y);
      }
    }
  }
  for (t = 0; t < i; ++t) {
    for (j = 0; j < m; ++j) {
      if (((s[t][j >> 2] >> (j & 3)) & 1) == 0) continue;
      (s[t][j >> 2] ^= (1 << (j & 3)));
      ++ans;
      for (q.init(), q.push((t << 14) + j); !q.empty();) {
        k = q.front();
        q.pop();
        a = k >> 14;
        b = k & 16383;
        for (z = 0; z < 4; ++z) {
          x = a + g[z][0];
          y = b + g[z][1];
          if (x < 0 || x >= i || y < 0 || y >= m ||
              ((s[x][y >> 2] >> (y & 3)) & 1) == 0)
            continue;
          (s[x][y >> 2] ^= (1 << (y & 3)));
          q.push((x << 14) + y);
        }
      }
    }
  }
  if (i == n) {
    printf("%d\n", ans);
    return 0;
  }
  for (; i < n; ++i)
    for (j = (m >> 2) - 1; ~j; --j) GET(s[i - t][j]);
  for (j = 0; j < m; ++j) {
    if (!block[j] || adj[block[j]].size() == 0) continue;
    q.init();
    for (auto &it : adj[block[j]])
      if (((s[0][it >> 2] >> (it & 3)) & 1) == 1) {
        (s[0][it >> 2] ^= (1 << (it & 3)));
        q.push((0 << 14) + it);
      }
    adj[block[j]].clear();
    for (; !q.empty();) {
      k = q.front();
      q.pop();
      a = k >> 14;
      b = k & 16383;
      if (a == 0) {
        if (block[b] && adj[block[b]].size() > 0) {
          --ans;
          for (auto &it : adj[block[b]])
            if (((s[0][it >> 2] >> (it & 3)) & 1) == 1) {
              (s[0][it >> 2] ^= (1 << (it & 3)));
              q.push((0 << 14) + it);
            }
          adj[block[b]].clear();
        }
      }
      for (z = 0; z < 4; ++z) {
        x = a + g[z][0];
        y = b + g[z][1];
        if (x < 0 || x >= n - t || y < 0 || y >= m ||
            ((s[x][y >> 2] >> (y & 3)) & 1) == 0)
          continue;
        (s[x][y >> 2] ^= (1 << (y & 3)));
        q.push((x << 14) + y);
      }
    }
  }
  for (i = 0; i < n - t; ++i) {
    for (j = 0; j < m; ++j) {
      if (((s[i][j >> 2] >> (j & 3)) & 1) == 0) continue;
      (s[i][j >> 2] ^= (1 << (j & 3)));
      ++ans;
      for (q.init(), q.push((i << 14) + j); !q.empty();) {
        k = q.front();
        q.pop();
        a = k >> 14;
        b = k & 16383;
        for (z = 0; z < 4; ++z) {
          x = a + g[z][0];
          y = b + g[z][1];
          if (x < 0 || x >= n - t || y < 0 || y >= m ||
              ((s[x][y >> 2] >> (y & 3)) & 1) == 0)
            continue;
          (s[x][y >> 2] ^= (1 << (y & 3)));
          q.push((x << 14) + y);
        }
      }
    }
  }
  printf("%d\n", ans);
  return 0;
}
