#include <bits/stdc++.h>
using namespace std;
int n, m;
char s[1 << 12];
int las[1 << 14];
int get(int x) {
  int v;
  if (s[x >> 2] >= '0' && s[x >> 2] <= '9')
    v = s[x >> 2] - '0';
  else
    v = s[x >> 2] - 'A' + 10;
  return v >> (3 ^ (x & 3)) & 1;
}
struct DSU {
  int fa[1 << 15], rnk[1 << 15], tme, t[1 << 15], cnt;
  DSU() {
    memset(t, -1, sizeof(t));
    tme = 0;
    cnt = 0;
  }
  void clear() {
    ++tme;
    cnt = 0;
  }
  int &get(int x) {
    if (t[x] == tme) return fa[x];
    t[x] = tme;
    rnk[x] = 1;
    return fa[x] = x;
  }
  int find(int x) { return get(x) == x ? x : get(x) = find(get(x)); }
  void merge(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return;
    if (rnk[x] < rnk[y]) swap(x, y);
    get(y) = x;
    rnk[x] += rnk[y];
    ++cnt;
  }
} dsu[2];
int fst[1 << 15];
int main() {
  scanf("%d %d", &n, &m);
  int ans = 0;
  int p = 0, q = 1;
  for (int i = 0; i < n; ++i) {
    scanf("%s", s);
    int cnt = 0;
    for (int j = 0; j < m; ++j) cnt += get(j);
    int nw = dsu[p].cnt;
    for (int j = 1; j < m; ++j)
      if (get(j) && get(j - 1)) dsu[p].merge(j + m - 1, j + m);
    if (i)
      for (int j = 0; j < m; ++j)
        if (get(j) && las[j]) dsu[p].merge(j + m, j);
    ans += cnt - (dsu[p].cnt - nw);
    memset(fst, -1, sizeof(fst));
    dsu[q].clear();
    for (int j = 0; j < m; ++j)
      if (!~fst[dsu[p].find(j + m)])
        fst[dsu[p].find(j + m)] = j;
      else
        dsu[q].merge(j, fst[dsu[p].find(j + m)]);
    swap(p, q);
    for (int j = 0; j < m; ++j) las[j] = get(j);
  }
  printf("%d\n", ans);
  return 0;
}
