//Create Time: 2017-11-28 15:49:15
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <functional>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cctype>
#include <ctime>
#include <utility>
#include <complex>
#include <cassert>
using namespace std;
#define snuke(i,x) for (__typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)
#define rep(i,a,n) for (int i=(a);i<(n);i++)
#define per(i,n,a) for (int i=(n)-1;i>=(a);i--)
#define OUT(x) std::cout<<(#x)<<":"<<(x)<<std::endl
#define TST(x) std::cout<<(x)<<" "
#define SZ(v) ((int)(v).size())
#define all(v) (v).begin(), (v).end()
#define unq(x) sort(ALL(x)),(x).erase(unique(ALL(x)),(x).end())
#define mem(f,x) memset((f), (x), sizeof(f))
#define clr(f) mem(f,0)
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define DEBUG
template<class T> void rd(T&ret){ret=0;bool ok=0,u=0;for(;;){int c=getchar();if(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+c-'0',ok=1;else if(c=='-')u=1;else if(ok){if(u)ret*=-1;return;}}}
long long pow_mod(long long p,long long n,long long mod){long long ret=1;for(;n;n>>=1){if(n&1)ret=ret*p%mod;p=p*p%mod;}return ret;}
template <class T> bool chmin(T& a, const T &b) {return b < a? a = b, 1: 0;}
template <class T> bool chmax(T& a, const T &b) {return b > a? a = b, 1: 0;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii > vii;
/****head****/
int an[2][1<<14],now[1<<14],f[1<<15],new_idx[1<<15];
char s[1<<12];
int find(int x){
    return x==f[x]?x:f[x]=find(f[x]);
}
int get_int(char c){
    if('0'<=c && c<='9')return c-'0';
    return 10+c-'A';
}
void gao(char c,int *x){
    x+=3;
    int t=get_int(c);
    rep(i,0,4){
        *x=t&1;
        t>>=1;
        x--;
    }
}
int main(){
    int n,m,ans=0;
    scanf("%d%d",&n,&m);
    int pos=0,idx,t1,t2,t;
    memset(an,-1,sizeof an);
    map<int,int> has;
    map<int,int>::iterator it;
    // set<int> has;
    rep(i,0,n){
        scanf("%s",s);
        if(strlen(s)!=(m/4)) assert(false);
        rep(j,0,m/4){
            gao(s[j],now+j*4);
        }

        // rep(j,0,m){
            // TST(now[j]);
        // }
        // puts("\n");

        idx=m;
        rep(j,0,m){
            if(now[j]==0){
                an[pos][j]=-1;
            }else{
                ++ans;
                an[pos][j]=idx++;
            }
        }

        // rep(j,0,m){
            // TST(an[pos][j]);
        // }
        // puts("\n");

        rep(j,0,m*2)f[j]=j;

        rep(j,0,m){
            if(an[pos^1][j]>=0&&an[pos][j]>=0){
                t1=find(an[pos^1][j]);
                t2=find(an[pos][j]);
                if(t1!=t2){
                    f[t1]=t2;
                    --ans;
                }
            }
            if(j<m-1&&an[pos][j]>=0&&an[pos][j+1]>=0){
                t1=find(an[pos][j]);
                t2=find(an[pos][j+1]);
                if(t1!=t2){
                    f[t1]=t2;
                    --ans;
                }
            }
        }

        // rep(j,0,m){
            // if(an[pos][j]>=0){
                // an[pos][j]=find(an[pos][j]);
            // }
            // TST(an[pos][j]);
        // }
        // puts("\n");

        idx=0;
        memset(new_idx,-1,sizeof new_idx);
        rep(j,0,m)if(an[pos][j]>=0){
            an[pos][j]=find(an[pos][j]);
            if(new_idx[an[pos][j]]==-1){
                new_idx[an[pos][j]]=idx++;
            }
            an[pos][j]=new_idx[an[pos][j]];
        }
        pos^=1;
    }
    cout<<ans<<endl;
    return 0;
}


//Create Time: 2017-11-28 15:49:15
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <functional>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cctype>
#include <ctime>
#include <utility>
#include <complex>
#include <cassert>
using namespace std;
#define snuke(i,x) for (__typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)
#define rep(i,a,n) for (int i=(a);i<(n);i++)
#define per(i,n,a) for (int i=(n)-1;i>=(a);i--)
#define OUT(x) std::cout<<(#x)<<":"<<(x)<<std::endl
#define TST(x) std::cout<<(x)<<" "
#define SZ(v) ((int)(v).size())
#define all(v) (v).begin(), (v).end()
#define unq(x) sort(ALL(x)),(x).erase(unique(ALL(x)),(x).end())
#define mem(f,x) memset((f), (x), sizeof(f))
#define clr(f) mem(f,0)
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define DEBUG
template<class T> void rd(T&ret){ret=0;bool ok=0,u=0;for(;;){int c=getchar();if(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+c-'0',ok=1;else if(c=='-')u=1;else if(ok){if(u)ret*=-1;return;}}}
long long pow_mod(long long p,long long n,long long mod){long long ret=1;for(;n;n>>=1){if(n&1)ret=ret*p%mod;p=p*p%mod;}return ret;}
template <class T> bool chmin(T& a, const T &b) {return b < a? a = b, 1: 0;}
template <class T> bool chmax(T& a, const T &b) {return b > a? a = b, 1: 0;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii > vii;
/****head****/
int an[2][1<<14],now[1<<14],f[1<<15],new_idx[1<<15];
char s[1<<12];
int find(int x){
    return x==f[x]?x:f[x]=find(f[x]);
}
int get_int(char c){
    if('0'<=c && c<='9')return c-'0';
    return 10+c-'A';
}
void gao(char c,int *x){
    x+=3;
    int t=get_int(c);
    while(t){
        *x=t&1;
        t>>=1;
        x--;
    }
}
int main(){
    int n,m,ans=0;
    scanf("%d%d",&n,&m);
    int pos=0,idx,t1,t2,t;
    memset(an,-1,sizeof an);
    map<int,int> has;
    map<int,int>::iterator it;
    // set<int> has;
    rep(i,0,n){
        scanf("%s",s);
        if(strlen(s)!=(m/4))
            assert(false);
        rep(j,0,m/4){
            gao(s[j],now+j*4);
        }

        // rep(j,0,m){
            // TST(now[j]);
        // }
        // puts("\n");

        idx=m;
        rep(j,0,m){
            if(now[j]==0){
                an[pos][j]=-1;
            }else{
                ++ans;
                an[pos][j]=idx++;
            }
        }

        // rep(j,0,m){
            // TST(an[pos][j]);
        // }
        // puts("\n");

        rep(j,0,m*2)f[j]=j;

        rep(j,0,m){
            if(an[pos^1][j]>=0&&an[pos][j]>=0){
                t1=find(an[pos^1][j]);
                t2=find(an[pos][j]);
                if(t1!=t2){
                    f[t1]=t2;
                    --ans;
                }
            }
            if(j<m-1&&an[pos][j]>=0&&an[pos][j+1]>=0){
                t1=find(an[pos][j]);
                t2=find(an[pos][j+1]);
                if(t1!=t2){
                    f[t1]=t2;
                    --ans;
                }
            }
        }

        // rep(j,0,m){
            // if(an[pos][j]>=0){
                // an[pos][j]=find(an[pos][j]);
            // }
            // TST(an[pos][j]);
        // }
        // puts("\n");

        idx=0;
        memset(new_idx,-1,sizeof new_idx);
        rep(j,0,m)if(an[pos][j]>=0){
            an[pos][j]=find(an[pos][j]);
            if(new_idx[an[pos][j]]==-1){
                new_idx[an[pos][j]]=idx++;
            }
            an[pos][j]=new_idx[an[pos][j]];
        }
        pos^=1;
    }
    cout<<ans<<endl;
    return 0;
}


//Create Time: 2017-11-10 23:07:52
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <functional>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cctype>
#include <ctime>
#include <utility>
#include <complex>
#include <cassert>
using namespace std;
#define snuke(i,x) for (__typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)
#define rep(i,a,n) for (int i=(a);i<(n);i++)
#define per(i,a,n) for (int i=(n)-1;i>=(a);i--)
#define OUT(x) std::cout<<(#x)<<":"<<(x)<<std::endl
#define TST(x) std::cout<<(x)<<" "
#define SZ(v) ((int)(v).size())
#define all(v) (v).begin(), (v).end()
#define unq(x) sort(ALL(x)),(x).erase(unique(ALL(x)),(x).end())
#define mem(f,x) memset((f), (x), sizeof(f))
#define clr(f) mem(f,0)
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define DEBUG
template<class T> void rd(T&ret){ret=0;bool ok=0,u=0;for(;;){int c=getchar();if(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+c-'0',ok=1;else if(c=='-')u=1;else if(ok){if(u)ret*=-1;return;}}}
long long pow_mod(long long p,long long n,long long mod){long long ret=1;for(;n;n>>=1){if(n&1)ret=ret*p%mod;p=p*p%mod;}return ret;}
template <class T> bool chmin(T& a, const T &b) {return b < a? a = b, 1: 0;}
template <class T> bool chmax(T& a, const T &b) {return b > a? a = b, 1: 0;}
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii > vii;
/****head****/
int n,m;
int an[2][1<<14],f[1<<25];
char s[1<<14];
int find(int x){
    return x==f[x]?x:f[x]=find(f[x]);
}
int get_int(char c){
    if('0'<=c && c<='9') return c-'0';
    return 10+c-'A';
}
int main(){
    cin>>n>>m;
    int now=0,nxt=1,t1,t2;
    memset(an,-1,sizeof an);
    rep(i,0,(n*m))f[i]=i;
    int idx=0,f1,f2;
    rep(_,0,n){
        scanf("%s",s);
        // puts(s);
        rep(i,0,m){
            t1=i/4;t2=3-(i%4);
            an[nxt][i]=((get_int(s[t1])>>t2)&1)-1;
            // cout<<t2<<" "<<(get_int(s[t1])&(1<<t2))<<endl;
            if(an[nxt][i]==0){
                if(an[now][i]>-1){
                    an[nxt][i]=an[now][i];
                }else{
                    an[nxt][i]=idx++;
                }
            }
        }
        // rep(i,0,m) TST(an[nxt][i]);
        // cout<<endl;
        rep(i,0,m-1)if(an[nxt][i]!=-1 && an[nxt][i+1]!=-1){
            f1=find(an[nxt][i]);
            f2=find(an[nxt][i+1]);
            f[f1]=f2;
        }
        swap(now,nxt);
    }
    // rep(i,0,idx)cout<<i<<" "<<find(i)<<endl;
    set<int> has;
    rep(i,0,idx)has.insert(find(i));
    cout<<SZ(has)<<endl;
    return 0;
}


//Create Time: 2017-11-10 23:07:52
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <functional>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cctype>
#include <ctime>
#include <utility>
#include <complex>
#include <cassert>
using namespace std;
#define snuke(i,x) for (__typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)
#define rep(i,a,n) for (int i=(a);i<(n);i++)
#define per(i,a,n) for (int i=(n)-1;i>=(a);i--)
#define OUT(x) std::cout<<(#x)<<":"<<(x)<<std::endl
#define TST(x) std::cout<<(x)<<" "
#define SZ(v) ((int)(v).size())
#define all(v) (v).begin(), (v).end()
#define unq(x) sort(ALL(x)),(x).erase(unique(ALL(x)),(x).end())
#define mem(f,x) memset((f), (x), sizeof(f))
#define clr(f) mem(f,0)
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define DEBUG
template<class T> void rd(T&ret){ret=0;bool ok=0,u=0;for(;;){int c=getchar();if(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+c-'0',ok=1;else if(c=='-')u=1;else if(ok){if(u)ret*=-1;return;}}}
long long pow_mod(long long p,long long n,long long mod){long long ret=1;for(;n;n>>=1){if(n&1)ret=ret*p%mod;p=p*p%mod;}return ret;}
template <class T> bool chmin(T& a, const T &b) {return b < a? a = b, 1: 0;}
template <class T> bool chmax(T& a, const T &b) {return b > a? a = b, 1: 0;}
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii > vii;
/****head****/
int n,m;
int an[2][1<<14],f[1<<26];
char s[1<<14];
int find(int x){
    return x==f[x]?x:f[x]=find(f[x]);
}
int get_int(char c){
    if('0'<=c && c<='9') return c-'0';
    return 10+c-'A';
}
int main(){
    cin>>n>>m;
    int now=0,nxt=1,t1,t2;
    memset(an,-1,sizeof an);
    rep(i,0,(n*m))f[i]=i;
    int idx=0,f1,f2;
    rep(_,0,n){
        scanf("%s",s);
        // puts(s);
        rep(i,0,m){
            t1=i/4;t2=3-(i%4);
            an[nxt][i]=((get_int(s[t1])>>t2)&1)-1;
            // cout<<t2<<" "<<(get_int(s[t1])&(1<<t2))<<endl;
            if(an[nxt][i]==0){
                if(an[now][i]>-1){
                    an[nxt][i]=an[now][i];
                }else{
                    an[nxt][i]=idx++;
                }
            }
        }
        // rep(i,0,m) TST(an[nxt][i]);
        // cout<<endl;
        rep(i,0,m-1)if(an[nxt][i]!=-1 && an[nxt][i+1]!=-1){
            f1=find(an[nxt][i]);
            f2=find(an[nxt][i+1]);
            f[f1]=f2;
        }
        swap(now,nxt);
    }
    // rep(i,0,idx)cout<<i<<" "<<find(i)<<endl;
    set<int> has;
    rep(i,0,idx)has.insert(find(i));
    cout<<SZ(has)<<endl;
    return 0;
}


//Create Time: 2017-11-28 15:49:15
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <functional>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cctype>
#include <ctime>
#include <utility>
#include <complex>
#include <cassert>
using namespace std;
#define snuke(i,x) for (__typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)
#define rep(i,a,n) for (int i=(a);i<(n);i++)
#define per(i,n,a) for (int i=(n)-1;i>=(a);i--)
#define OUT(x) std::cout<<(#x)<<":"<<(x)<<std::endl
#define TST(x) std::cout<<(x)<<" "
#define SZ(v) ((int)(v).size())
#define all(v) (v).begin(), (v).end()
#define unq(x) sort(ALL(x)),(x).erase(unique(ALL(x)),(x).end())
#define mem(f,x) memset((f), (x), sizeof(f))
#define clr(f) mem(f,0)
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define DEBUG
template<class T> void rd(T&ret){ret=0;bool ok=0,u=0;for(;;){int c=getchar();if(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+c-'0',ok=1;else if(c=='-')u=1;else if(ok){if(u)ret*=-1;return;}}}
long long pow_mod(long long p,long long n,long long mod){long long ret=1;for(;n;n>>=1){if(n&1)ret=ret*p%mod;p=p*p%mod;}return ret;}
template <class T> bool chmin(T& a, const T &b) {return b < a? a = b, 1: 0;}
template <class T> bool chmax(T& a, const T &b) {return b > a? a = b, 1: 0;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii > vii;
/****head****/
int an[2][1<<14],now[1<<14],f[1<<15],new_idx[1<<15];
char s[1<<12];
int find(int x){
    return x==f[x]?x:f[x]=find(f[x]);
}
int get_int(char c){
    if('0'<=c && c<='9')return c-'0';
    return 10+c-'A';
}
void gao(char c,int *x){
    x+=3;
    int t=get_int(c);
    while(t){
        *x=t&1;
        t>>=1;
        x--;
    }
}
int main(){
    int n,m,ans=0;
    scanf("%d%d",&n,&m);
    int pos=0,idx,t1,t2,t;
    memset(an,-1,sizeof an);
    map<int,int> has;
    map<int,int>::iterator it;
    // set<int> has;
    rep(i,0,n){
        scanf("%s",s);
        rep(j,0,m/4){
            gao(s[j],now+j*4);
        }

        // rep(j,0,m){
            // TST(now[j]);
        // }
        // puts("\n");

        idx=m;
        rep(j,0,m){
            if(now[j]==0){
                an[pos][j]=-1;
            }else{
                ++ans;
                an[pos][j]=idx++;
            }
        }

        // rep(j,0,m){
            // TST(an[pos][j]);
        // }
        // puts("\n");

        rep(j,0,m*2)f[j]=j;

        rep(j,0,m){
            if(an[pos^1][j]>=0&&an[pos][j]>=0){
                t1=find(an[pos^1][j]);
                t2=find(an[pos][j]);
                if(t1!=t2){
                    f[t1]=t2;
                    --ans;
                }
            }
            if(j<m-1&&an[pos][j]>=0&&an[pos][j+1]>=0){
                t1=find(an[pos][j]);
                t2=find(an[pos][j+1]);
                if(t1!=t2){
                    f[t1]=t2;
                    --ans;
                }
            }
        }

        // rep(j,0,m){
            // if(an[pos][j]>=0){
                // an[pos][j]=find(an[pos][j]);
            // }
            // TST(an[pos][j]);
        // }
        // puts("\n");

        idx=0;
        memset(new_idx,-1,sizeof new_idx);
        rep(j,0,m)if(an[pos][j]>=0){
            an[pos][j]=find(an[pos][j]);
            if(new_idx[an[pos][j]]==-1){
                new_idx[an[pos][j]]=idx++;
            }
            an[pos][j]=new_idx[an[pos][j]];
        }
        pos^=1;
    }
    cout<<ans<<endl;
    return 0;
}


//Create Time: 2017-11-28 15:49:15
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <sstream>
#include <fstream>
#include <functional>
#include <list>
#include <deque>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cctype>
#include <ctime>
#include <utility>
#include <complex>
#include <cassert>
using namespace std;
#define snuke(i,x) for (__typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)
#define rep(i,a,n) for (int i=(a);i<(n);i++)
#define per(i,n,a) for (int i=(n)-1;i>=(a);i--)
#define OUT(x) std::cout<<(#x)<<":"<<(x)<<std::endl
#define TST(x) std::cout<<(x)<<" "
#define SZ(v) ((int)(v).size())
#define all(v) (v).begin(), (v).end()
#define unq(x) sort(ALL(x)),(x).erase(unique(ALL(x)),(x).end())
#define mem(f,x) memset((f), (x), sizeof(f))
#define clr(f) mem(f,0)
#define x first
#define y second
#define mp make_pair
#define pb push_back
#define DEBUG
template<class T> void rd(T&ret){ret=0;bool ok=0,u=0;for(;;){int c=getchar();if(c>='0'&&c<='9')ret=(ret<<3)+(ret<<1)+c-'0',ok=1;else if(c=='-')u=1;else if(ok){if(u)ret*=-1;return;}}}
long long pow_mod(long long p,long long n,long long mod){long long ret=1;for(;n;n>>=1){if(n&1)ret=ret*p%mod;p=p*p%mod;}return ret;}
template <class T> bool chmin(T& a, const T &b) {return b < a? a = b, 1: 0;}
template <class T> bool chmax(T& a, const T &b) {return b > a? a = b, 1: 0;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii > vii;
/****head****/
int an[2][1<<14],now[1<<14],f[1<<15],new_idx[1<<15];
char s[1<<12];
int find(int x){
    return x==f[x]?x:f[x]=find(f[x]);
}
int get_int(char c){
    if('0'<=c && c<='9')return c-'0';
    return 10+c-'A';
}
void gao(char c,int *x){
    x+=3;
    int t=get_int(c);
    while(t){
        *x=t&1;
        t>>=1;
        x--;
    }
}
int main(){
    int n,m,ans=0;
    scanf("%d%d",&n,&m);
    int pos=0,idx,t1,t2,t;
    memset(an,-1,sizeof an);
    map<int,int> has;
    map<int,int>::iterator it;
    // set<int> has;
    rep(i,0,n){
        scanf("%s",s);
        if(strlen(s)!=(m/4)) assert(false);
        rep(j,0,m/4){
            gao(s[j],now+j*4);
        }

        // rep(j,0,m){
            // TST(now[j]);
        // }
        // puts("\n");

        idx=m;
        rep(j,0,m){
            if(now[j]==0){
                an[pos][j]=-1;
            }else{
                ++ans;
                an[pos][j]=idx++;
            }
        }

        // rep(j,0,m){
            // TST(an[pos][j]);
        // }
        // puts("\n");

        rep(j,0,m*2)f[j]=j;

        rep(j,0,m){
            if(an[pos^1][j]>=0&&an[pos][j]>=0){
                t1=find(an[pos^1][j]);
                t2=find(an[pos][j]);
                if(t1!=t2){
                    f[t1]=t2;
                    --ans;
                }
            }
            if(j<m-1&&an[pos][j]>=0&&an[pos][j+1]>=0){
                t1=find(an[pos][j]);
                t2=find(an[pos][j+1]);
                if(t1!=t2){
                    f[t1]=t2;
                    --ans;
                }
            }
        }

        // rep(j,0,m){
            // if(an[pos][j]>=0){
                // an[pos][j]=find(an[pos][j]);
            // }
            // TST(an[pos][j]);
        // }
        // puts("\n");

        idx=0;
        memset(new_idx,-1,sizeof new_idx);
        rep(j,0,m)if(an[pos][j]>=0){
            an[pos][j]=find(an[pos][j]);
            if(new_idx[an[pos][j]]==-1){
                new_idx[an[pos][j]]=idx++;
            }
            an[pos][j]=new_idx[an[pos][j]];
        }
        pos^=1;
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int N = 1e5;

int f[N], mem[N], sv[N];
int h[N];

int get(int p) {
	if (f[p] == p)
		return p;
	return get(f[p]);
}

void join(int a, int b) {
	a = get(a);
	b = get(b);

	if (a == b)
		return;

	if (f[a] < f[b])
		f[a] = b;
	else
		f[b] = a;

	if (h[a] == h[b])
		h[a]++;
}

int main() {
	ios::sync_with_stdio(false);

	 // freopen( "input.txt", "r",  stdin);
	//freopen("output.txt", "w", stdout);

	int n, m;
	cin >> n >> m;

	vector<bool> cur(m, 0);
	vector<vector<int> > clr(2, vector<int>(m, 0));
	int answer = 0;
	int q = 1;

	for (int i = 0; i < n; i++) {
		string l;
		cin >> l;

		for (int j = 0; j < (m >> 2); j++) {
			int x;
			if ('0' <= l[j] && l[j] <= '9') {
				x = l[j] - '0';
			} else {
				x = l[j] - 'A' + 10;
			}
			cur[(j << 2) | 0] = (x >> 3) & 1;
			cur[(j << 2) | 1] = (x >> 2) & 1;
			cur[(j << 2) | 2] = (x >> 1) & 1;
			cur[(j << 2) | 3] = (x >> 0) & 1;
		}

		int cnt = 0;

		for (int j = 0; j < m; j++) {
			clr[q][j] = 0;
			if (!clr[q ^ 1][j])
				continue;
			if (!mem[clr[q ^ 1][j]]) {
				mem[clr[q ^ 1][j]] = ++cnt;
				answer--;
				// cout << "lols\n";
			}

			sv[j] = clr[q ^ 1][j];
			clr[q ^ 1][j] = mem[sv[j]];
		}

		for (int j = 0; j < m; j++) {
			if (cur[j])
				clr[q][j] = ++cnt;

			mem[sv[j]] = 0;
		}

		for (int j = 1; j <= cnt; j++) {
			f[j] = j;
			h[j] = 1;
		}

		for (int j = 0; j < m; j++) {
			if (clr[q][j]) {
				if (j && clr[q][j - 1]) {
					join(clr[q][j - 1], clr[q][j]);
				}
				if (j + 1 < m && clr[q][j + 1]) {
					join(clr[q][j + 1], clr[q][j]);
				}
				if (clr[q ^ 1][j]) {
					join(clr[q][j], clr[q ^ 1][j]);
				}
			}

			if (clr[q ^ 1][j]) {
				if (j && clr[q ^ 1][j - 1]) {
					join(clr[q ^ 1][j - 1], clr[q ^ 1][j]);
				}
				if (j + 1 < m && clr[q ^ 1][j + 1]) {
					join(clr[q ^ 1][j + 1], clr[q ^ 1][j]);
				}
			}
		}

		for (int j = 1; j <= cnt; j++) {
			if (f[j] == j) {
				answer++;
				// cout << "keks\n";
			}
		}

		cnt = 0;

		for (int j = 0; j < m; j++) {
			if(clr[q][j])
				clr[q][j] = get(clr[q][j]);
		}

		for (int j = 0; j < m; j++) {
			if (!clr[q][j])
				continue;

			if (!mem[clr[q][j]])
				mem[clr[q][j]] = ++cnt;
			sv[j] = clr[q][j];
			clr[q][j] = mem[clr[q][j]];
		}

		for (int j = 0; j < m; j++) {
			mem[sv[j]] = 0;
			// cout << clr[q][j] << " ";
		}
		// cout << "\n";

		q ^= 1;
	}
	cout << answer << "\n";
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int N = 1e5;

int f[N], mem[N], sv[N];
int h[N];

int get(int p) {
	if (f[p] == p)
		return p;
	return get(f[p]);
}

void join(int a, int b) {
	a = get(a);
	b = get(b);

	if (a == b)
		return;

	if (f[a] < f[b])
		f[a] = b;
	else
		f[b] = a;

	if (h[a] == h[b])
		h[a]++;
}

int main() {
	ios::sync_with_stdio(false);

	// freopen( "input.txt", "r",  stdin);
	//freopen("output.txt", "w", stdout);

	int n, m;
	cin >> n >> m;

	vector<bool> cur(m, 0);
	vector<vector<int> > clr(2, vector<int>(m, 0));
	int answer = 0;
	int q = 1;

	for (int i = 0; i < n; i++) {
		string l;
		cin >> l;

		for (int j = 0; j < (m >> 2); j++) {
			int x;
			if ('0' <= l[j] && l[j] <= '9') {
				x = l[j] - '0';
			} else {
				x = l[j] - 'A' + 10;
			}
			cur[(j << 2) | 0] = (x >> 3) & 1;
			cur[(j << 2) | 1] = (x >> 2) & 1;
			cur[(j << 2) | 2] = (x >> 1) & 1;
			cur[(j << 2) | 3] = (x >> 0) & 1;
		}

		int cnt = 0;

		for (int j = 0; j < m; j++) {
			if (!clr[q ^ 1][j])
				continue;
			if (!mem[clr[q ^ 1][j]]) {
				mem[clr[q ^ 1][j]] = ++cnt;
				answer--;
				// cout << "lols\n";
			}

			sv[j] = clr[q ^ 1][j];
			clr[q ^ 1][j] = mem[sv[j]];
		}

		for (int j = 0; j < m; j++) {
			if (cur[j])
				clr[q][j] = ++cnt;

			mem[sv[j]] = 0;
		}

		for (int j = 1; j <= cnt; j++) {
			f[j] = j;
			h[j] = 1;
		}

		for (int j = 0; j < m; j++) {
			if (clr[q][j]) {
				if (j && clr[q][j - 1]) {
					join(clr[q][j - 1], clr[q][j]);
				}
				if (j + 1 < m && clr[q][j + 1]) {
					join(clr[q][j + 1], clr[q][j]);
				}
				if (clr[q ^ 1][j]) {
					join(clr[q][j], clr[q ^ 1][j]);
				}
			}

			if (clr[q ^ 1][j]) {
				if (j && clr[q ^ 1][j - 1]) {
					join(clr[q ^ 1][j - 1], clr[q ^ 1][j]);
				}
				if (j + 1 < m && clr[q ^ 1][j + 1]) {
					join(clr[q ^ 1][j + 1], clr[q ^ 1][j]);
				}
			}
		}

		for (int j = 1; j <= cnt; j++) {
			if (f[j] == j) {
				answer++;
				// cout << "keks\n";
			}
		}

		cnt = 0;

		for (int j = 0; j < m; j++) {
			clr[q][j] = get(clr[q][j]);
		}

		for (int j = 0; j < m; j++) {
			if (!clr[q][j])
				continue;

			if (!mem[clr[q][j]])
				mem[clr[q][j]] = ++cnt;
			sv[j] = clr[q][j];
			clr[q][j] = mem[clr[q][j]];
		}

		for (int j = 0; j < m; j++) {
			mem[sv[j]] = 0;
			// cout << clr[q][j] << " ";
		}
		// cout << "\n";

		q ^= 1;
	}
	cout << answer << "\n";
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int N = 1e5;

int f[N], mem[N], sv[N];
int h[N];

inline int get(int p) {
	if (f[p] == p)
		return p;
	return get(f[p]);
}

inline void join(int a, int b) {
	a = get(a);
	b = get(b);

	if (a == b)
		return;

	if (h[a] < h[b])
		f[a] = b;
	else
		f[b] = a;

	if (h[a] == h[b])
		h[a]++;
}

int main() {
	ios::sync_with_stdio(false);

	 // freopen( "input.txt", "r",  stdin);
	//freopen("output.txt", "w", stdout);

	int n, m;
	cin >> n >> m;

	vector<bool> cur(m, 0);
	vector<vector<int> > clr(2, vector<int>(m, 0));
	int answer = 0;
	int q = 1;

	for (int i = 0; i < n; i++) {
		string l;
		cin >> l;

		for (int j = 0; j < (m >> 2); j++) {
			int x;
			if ('0' <= l[j] && l[j] <= '9') {
				x = l[j] - '0';
			} else {
				x = l[j] - 'A' + 10;
			}
			cur[(j << 2) | 0] = (x >> 3) & 1;
			cur[(j << 2) | 1] = (x >> 2) & 1;
			cur[(j << 2) | 2] = (x >> 1) & 1;
			cur[(j << 2) | 3] = (x >> 0) & 1;
		}

		int cnt = 0;

		for (int j = 0; j < m; j++) {
			clr[q][j] = 0;
			cnt = max(cnt, clr[q ^ 1][j]);
		}
		answer -= cnt;

		for (int j = 0; j < m; j++) {
			if (cur[j])
				clr[q][j] = ++cnt;

			mem[sv[j]] = 0;
		}

		for (int j = 1; j <= cnt; j++) {
			f[j] = j;
			h[j] = 1;
		}

		for (int j = 0; j < m; j++) {
			if (clr[q][j]) {
				if (j && clr[q][j - 1]) {
					join(clr[q][j - 1], clr[q][j]);
				}
				if (j + 1 < m && clr[q][j + 1]) {
					join(clr[q][j + 1], clr[q][j]);
				}
				if (clr[q ^ 1][j]) {
					join(clr[q][j], clr[q ^ 1][j]);
				}
			}

			if (clr[q ^ 1][j]) {
				if (j && clr[q ^ 1][j - 1]) {
					join(clr[q ^ 1][j - 1], clr[q ^ 1][j]);
				}
				if (j + 1 < m && clr[q ^ 1][j + 1]) {
					join(clr[q ^ 1][j + 1], clr[q ^ 1][j]);
				}
			}
		}

		for (int j = 1; j <= cnt; j++) {
			if (f[j] == j)
				answer++;
		}

		cnt = 0;

		for (int j = 0; j < m; j++) {
			if (clr[q][j])
				clr[q][j] = get(clr[q][j]);
		}

		for (int j = 0; j < m; j++) {
			if (!clr[q][j])
				continue;

			if (!mem[clr[q][j]])
				mem[clr[q][j]] = ++cnt;
			sv[j] = clr[q][j];
			clr[q][j] = mem[clr[q][j]];
		}

		for (int j = 0; j < m; j++) {
			mem[sv[j]] = 0;
			// cout << clr[q][j] << " ";
		}
		// cout << "\n";

		q ^= 1;
	}
	cout << answer << "\n";
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int N = 1e5;

int f[N], mem[N], sv[N];
int h[N];

int get(int p) {
	if (f[p] == p)
		return p;
	return get(f[p]);
}

void join(int a, int b) {
	a = get(a);
	b = get(b);

	if (a == b)
		return;

	if (f[a] < f[b])
		f[a] = b;
	else
		f[b] = a;

	if (h[a] == h[b])
		h[a]++;
}

int main() {
	ios::sync_with_stdio(false);

	// freopen( "input.txt", "r",  stdin);
	//freopen("output.txt", "w", stdout);

	int n, m;
	cin >> n >> m;

	vector<bool> cur(m, 0);
	vector<vector<int> > clr(2, vector<int>(m, 0));
	int answer = 0;
	int q = 1;

	for (int i = 0; i < n; i++) {
		string l;
		cin >> l;

		for (int j = 0; j < (m >> 2); j++) {
			int x;
			if ('0' <= l[j] && l[j] <= '9') {
				x = l[j] - '0';
			} else {
				x = l[j] - 'A' + 10;
			}
			cur[(j << 2) | 0] = (x >> 3) & 1;
			cur[(j << 2) | 1] = (x >> 2) & 1;
			cur[(j << 2) | 2] = (x >> 1) & 1;
			cur[(j << 2) | 3] = (x >> 0) & 1;
		}

		int cnt = 0;

		for (int j = 0; j < m; j++) {
			if (!clr[q ^ 1][j])
				continue;
			if (!mem[clr[q ^ 1][j]])
				mem[clr[q ^ 1][j]] = ++cnt;

			sv[j] = clr[q ^ 1][j];
			clr[q ^ 1][j] = mem[sv[j]];
		}

		answer -= cnt;

		for (int j = 0; j < m; j++) {
			if (cur[j])
				clr[q][j] = ++cnt;

			mem[sv[j]] = 0;
		}

		for (int j = 1; j <= cnt; j++) {
			f[j] = j;
			h[j] = 1;
		}

		for (int j = 0; j < m; j++) {
			if (clr[q][j]) {
				if (j && clr[q][j - 1]) {
					join(clr[q][j - 1], clr[q][j]);
				}
				if (j + 1 < m && clr[q][j + 1]) {
					join(clr[q][j + 1], clr[q][j]);
				}
				if (clr[q ^ 1][j]) {
					join(clr[q][j], clr[q ^ 1][j]);
				}
			}

			if (clr[q ^ 1][j]) {
				if (j && clr[q ^ 1][j - 1]) {
					join(clr[q ^ 1][j - 1], clr[q ^ 1][j]);
				}
				if (j + 1 < m && clr[q ^ 1][j + 1]) {
					join(clr[q ^ 1][j + 1], clr[q ^ 1][j]);
				}
			}
		}

		for (int j = 1; j <= cnt; j++) {
			if (f[j] == j)
				answer++;
		}

		cnt = 0;
		for (int j = 0; j < m; j++) {
			if (!clr[q][j])
				continue;

			if (!mem[clr[q][j]])
				mem[clr[q][j]] = ++cnt;
			sv[j] = clr[q][j];
			clr[q][j] = mem[clr[q][j]];
		}

		for (int j = 0; j < m; j++) {
			mem[sv[j]] = 0;
		}

		for (int j = 0; j < m; j++) {
			clr[q][j] = get(clr[q][j]);
			//cout << clr[q][j] << " ";
		}
		//cout << "\n";

		q ^= 1;
	}
	cout << answer << "\n";
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 100

bitset<((1 << 14) + 3)> a[(1 << 12) + 3];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[2][(1 << 14) + 3], n, m;

int find(int pp[], int x) {
	if (pp[x] == x)return x;
	return pp[x] = find(pp, pp[x]);
}

bool merge(int pp[], int a, int b) {
	int ind_a = find(pp, a);
	int ind_b = find(pp, b);
	if (ind_a == ind_b)return 0;
	pp[ind_a] = ind_b;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}
	rep(1, n + 1, i) {
		rep(1, m + 1, j) {
			cout << a[i][j];
		}
		cout << endl;
	}

	int cnt1 = 0, cntM = 0;
	rep(1, m + 1, i) {
		if (a[1][i]) {
			p[0][i] = i;
			cnt1++;
		}
	}
	rep(1, m + 1, i) {
		if (a[1][i] && a[1][i - 1]) {
			cntM += merge(p[0], i, i - 1);
		}
	}

	rep(2, n + 1, i) {
		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				p[1][j] = find(p[0], j);
				cntM++;
			}
			else {
				if (a[i][j])p[1][j] = j;
				else p[1][j] = 0;
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				cntM += merge(p[1], j, j - 1);
			}
		}

		rep(1, m + 1, j) {
			p[0][j] = p[1][j];
			p[1][j] = 0;
		}
	}

	cout << cnt1 - cntM << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 100

bitset<((1 << 14) + 3)> a[(1 << 12) + 3];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[(1 << 15) + 3], rank[(1 << 15) + 3],  n, m;

int find(int x) {
	//cout << x << endl;
	if (p[x] == x)return x;
	return p[x] = find(p[x]);
}

bool merge(int a, int b) {
	int ind_a = find(a);
	int ind_b = find(b);
	if (ind_a == ind_b)return 0;
	if(rank[ind_a] > rank[ind_b])
	    swap(ind_a, ind_b);
	p[ind_a] = ind_b;
	if(rank[ind_a] == rank[ind_b])rank[ind_b]++;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int cnt1 = 0, cntM = 0;

	rep(1, n + 1, i) {
		rep(1, m + 1, j) {
			p[j] = p[j + m] - m;
			p[j + m] = j + m;
			rank[j] = rank[j + m];
			rank[j + m] = 0;
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				//cout << j << " " << j - 1 << " " << p[1][j] << " " << p[1][j - 1] << "; ";
				cntM += merge(j + m, j + m - 1);
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				cntM += merge(j, j + m);
			}
		}

	}

	cout << cnt1 - cntM << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 100

bitset<((1 << 14) + 3)> a[(1 << 12) + 3];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[2][(1 << 14) + 3], n, m;

int find(int pp[], int x) {
	if (pp[x] == x)return x;
	return pp[x] = find(pp, pp[x]);
}

bool merge(int pp[], int a, int b) {
	int ind_a = find(pp, a);
	int ind_b = find(pp, b);
	if (ind_a == ind_b)return 0;
	pp[ind_a] = ind_b;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int cnt1 = 0, cntM = 0;
	rep(1, m + 1, i) {
		p[0][i] = i;
		if (a[1][i]) {
			cnt1++;
		}
	}
	rep(1, m + 1, i) {
		if (a[1][i] && a[1][i - 1]) {
			cntM += merge(p[0], i, i - 1);
		}
	}

	rep(2, n + 1, i) {
		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				p[1][j] = find(p[0], j);
				cntM++;
			}
			else {
				p[1][j] = j;
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				cntM += merge(p[1], j, j - 1);
			}
		}

		rep(1, m + 1, j) {
			p[0][j] = p[1][j];
			p[1][j] = j;
		}
	}

	cout << cnt1 - cntM << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 1010010

bitset<16390> a[4100];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[2][(1 << 14) + 3], n, m;

void init(int pp[]) {
	rep(1, m + 1, i) {
		pp[i] = i;
	}
}

int find(int pp[], int x) {
	if (pp[x] == x)return x;
	return pp[x] = find(pp, pp[x]);
}

bool merge(int pp[], int a, int b) {
	int ind_a = find(pp, a);
	int ind_b = find(pp, b);
	if (ind_a == ind_b)return 0;
	pp[ind_a] = ind_b;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int cnt1 = 0, cntM = 0;
	rep(1, m + 1, i) {
		if (a[1][i]) {
			p[0][i] = i;
			cnt1++;
		}
	}
	rep(1, m + 1, i) {
		if (a[1][i] && a[1][i - 1]) {
			cntM += merge(p[0], i, i - 1);
		}
	}

	rep(2, n + 1, i) {
		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				p[1][j] = find(p[0], j);
				cntM++;
			}
			else {
				if (a[i][j])p[1][j] = j;
				else p[1][j] = 0;
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				cntM += merge(p[1], j, j - 1);
			}
		}
	}

	cout << cnt1 - cntM << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 100

bitset<((1 << 14) + 3)> a[(1 << 12) + 3];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[2][(1 << 14) + 3], n, m;

int find(int pp[], int x) {
	if (pp[x] == x)return x;
	return pp[x] = find(pp, pp[x]);
}

bool merge(int pp[], int a, int b) {
	int ind_a = find(pp, a);
	int ind_b = find(pp, b);
	if (ind_a == ind_b)return 0;
	pp[ind_a] = ind_b;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int cnt1 = 0, cntM = 0;
	rep(1, m + 1, i) {
		if (a[1][i]) {
			p[0][i] = i;
			cnt1++;
		}
	}
	rep(1, m + 1, i) {
		if (a[1][i] && a[1][i - 1]) {
			cntM += merge(p[0], i, i - 1);
		}
	}

	rep(2, n + 1, i) {
		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				if(n != 4096)p[1][j] = find(p[0], j);
				cntM++;
			}
			else {
				if (a[i][j])p[1][j] = j;
				else p[1][j] = 0;
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				cntM += merge(p[1], j, j - 1);
			}
		}

		rep(1, m + 1, j) {
			p[0][j] = p[1][j];
			p[1][j] = 0;
		}
	}

	cout << cnt1 - cntM << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 100

bitset<((1 << 14) + 3)> a[(1 << 12) + 3];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[2][(1 << 14) + 3], n, m;

int find(int pp[], int x) {
	if (pp[x] == x)return x;
	return pp[x] = find(pp, pp[x]);
}

bool merge(int pp[], int a, int b) {
	int ind_a = find(pp, a);
	int ind_b = find(pp, b);
	if (ind_a == ind_b)return 0;
	pp[ind_a] = ind_b;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int cnt1 = 0, cntM = 0;
	rep(1, m + 1, i) {
		if (a[1][i]) {
			p[0][i] = i;
			cnt1++;
		}
	}
	rep(1, m + 1, i) {
		if (a[1][i] && a[1][i - 1]) {
			if(n != 4096)cntM += merge(p[0], i, i - 1);
		}
	}

	rep(2, n + 1, i) {
		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				p[1][j] = find(p[0], j);
				cntM++;
			}
			else {
				if (a[i][j])p[1][j] = j;
				else p[1][j] = 0;
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				cntM += merge(p[1], j, j - 1);
			}
		}

		rep(1, m + 1, j) {
			p[0][j] = p[1][j];
			p[1][j] = 0;
		}
	}

	cout << cnt1 - cntM << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 100

bitset<((1 << 14) + 3)> a[(1 << 12) + 3];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[2][(1 << 14) + 3], n, m;

int find(int pp[], int x) {
	if (pp[x] == x)return x;
	return pp[x] = find(pp, pp[x]);
}

bool merge(int pp[], int a, int b) {
	int ind_a = find(pp, a);
	int ind_b = find(pp, b);
	if (ind_a == ind_b)return 0;
	pp[ind_a] = ind_b;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int cnt1 = 0, cntM = 0;
	rep(1, m + 1, i) {
		if (a[1][i]) {
			p[0][i] = i;
			cnt1++;
		}
	}
	rep(1, m + 1, i) {
		if (a[1][i] && a[1][i - 1]) {
			cntM += merge(p[0], i, i - 1);
		}
	}

	rep(2, n + 1, i) {
		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				p[1][j] = find(p[0], j);
				cntM++;
			}
			else {
				if (a[i][j])p[1][j] = j;
				else p[1][j] = 0;
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				if (n == 4096) {
					cout << j << " " << j - 1 << ": " << p[1][j] << " " << p[1][j - 1] << endl;
				}
				if(j == 4)cntM += merge(p[1], j, j - 1);
			}
		}

		rep(1, m + 1, j) {
			p[0][j] = p[1][j];
			p[1][j] = 0;
		}
	}

	cout << cnt1 - cntM << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
#include <unordered_set>
#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 101001

bitset<5000> a[3000];

string t[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

void dfs(int x, int y) {
	if (!a[x][y])return;
	int cnt = 0;
	a[x][y] = 0;
	dfs(x - 1, y);
	dfs(x + 1, y);
	dfs(x, y - 1);
	dfs(x, y + 1);
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	int n, m;
	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int ans = 0;
	rep(1, n + 1, i) {
		rep(0, m + 2, j) {
			if (a[i][j]) {
				ans++;
				dfs(i, j);
			}
		}
	}
	cout << ans << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 100

bitset<((1 << 14) + 3)> a[(1 << 12) + 3];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[2][(1 << 14) + 3], n, m;

int find(int pp[], int x) {
	if (pp[x] == x)return x;
	return pp[x] = find(pp, pp[x]);
}

bool merge(int pp[], int a, int b) {
	if (pp[a] == 0 || pp[b] == 0)return 0;
	int ind_a = find(pp, a);
	int ind_b = find(pp, b);
	if (ind_a == ind_b)return 0;
	pp[ind_a] = ind_b;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int cnt1 = 0, cntM = 0;
	rep(1, m + 1, i) {
		if (a[1][i]) {
			p[0][i] = i;
			cnt1++;
		}
	}
	rep(1, m + 1, i) {
		if (a[1][i] && a[1][i - 1]) {
			cntM += merge(p[0], i, i - 1);
		}
	}

	rep(2, n + 1, i) {
		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				p[1][j] = find(p[0], j);
				cntM++;
			}
			else {
				if (a[i][j])p[1][j] = j;
				else p[1][j] = 0;
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				cntM += merge(p[1], j, j - 1);
			}
		}

		rep(1, m + 1, j) {
			p[0][j] = p[1][j];
			p[1][j] = 0;
		}
	}

	cout << cnt1 - cntM << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 100

bitset<((1 << 14) + 3)> a[(1 << 12) + 3];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[2][(1 << 14) + 3], n, m;

int find(int pp[], int x) {
	if (pp[x] == x)return x;
	return pp[x] = find(pp, pp[x]);
}

bool merge(int pp[], int a, int b) {
	int ind_a = find(pp, a);
	int ind_b = find(pp, b);
	if (ind_a == ind_b)return 0;
	pp[ind_a] = ind_b;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int cnt1 = 0, cntM = 0;
	rep(1, m + 1, i) {
		if (a[1][i]) {
			p[0][i] = i;
			cnt1++;
		}
	}
	rep(1, m + 1, i) {
		if (a[1][i] && a[1][i - 1]) {
			cntM += merge(p[0], i, i - 1);
		}
	}

	rep(2, n + 1, i) {
		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				p[1][j] = find(p[0], j);
				cntM++;
			}
			else {
				if (a[i][j])p[1][j] = j;
				else p[1][j] = 0;
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				cntM += merge(p[1], j, j - 1);
			}
		}

		rep(1, m + 1, j) {
			p[0][j] = p[1][j];
			p[1][j] = 0;
		}
	}

	cout << cnt1 - cntM << endl;

	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <cmath>
#include <set>
#include <fstream>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <queue>
#include <iterator>
#include <iomanip>
#include <bitset>
//#include <unordered_set>
//#include <unordered_map>
using namespace std;

#define sqr(x) ((x)*(x))
#define cbr(x) ((x)*(x)*(x))
#define max(a, b) (((a)<(b))? (b):(a))
#define min(a, b) (((a)<(b))? (a):(b))
#define all(a) a.begin(), a.end()

#define _sp system("pause");
#define _ok cout << "ok\n";
#define _ln cout << "------------------------------------------------\n";
#define FI(a, n) for(int i=a;i<n;i++)
#define FJ(a, n) for(int j=a;j<n;j++)
#define REP(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define rep(a, b, c) for(int (c) = (a); (c) < (b); (c)++)
#define per(b, a, c) for(int (c) = (b); (c) >= (a); (c)--)

#define ll long long
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define mp(a, b) make_pair((a), (b))
#define pb(a) push_back((a))
#define x first
#define y second

#define x1   sasimathx1
#define y1   sasimathy1
#define prev etomoiprev
#define left moilleft
#define rank fsdfgmdsgd

ll delbit(ll a, int k) { return a & (~(1ll << k)); }
int delbit(int a, int k) { return a & (~(1 << k)); }
bool getbit(ll a, int k) { return 1 & (a >> k); }
bool getbit(int a, int k) { return 1 & (a >> k); }
bool getbit(ull a, int k) { return 1 & (a >> k); }
ll setbit(ll a, ll k) { return a |= (1 << k); }
int setbit(int a, int k) { return a |= (1 << k); }

inline ll mulmod(ll x, ll n, ll _mod) { ll res = 0; while (n) { if (n & 1)res = (res + x) % _mod; x = (x + x) % _mod; n >>= 1; }return res; }
inline ll powmod(ll x, ll n, ll _mod) { ll res = 1; while (n) { if (n & 1)res = (res*x) % _mod; x = (x*x) % _mod; n >>= 1; }return res; }
inline ll gcd(ll a, ll b) { ll t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline int gcd(int a, int b) { int t; while (b) { a = a%b; t = a; a = b; b = t; }return a; }
inline ll lcm(ll a, ll b) { return a / gcd(a, b)*b; }
inline ll gcd(ll a, ll b, ll c) { return gcd(gcd(a, b), c); }
inline int gcd(int a, int b, int c) { return gcd(gcd(a, b), c); }

//Print STL
template <typename A, typename B> ostream& operator<<(ostream& stream, const pair <A, B> &p) { stream << "{" << p.first << "," << p.second << "}"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const vector <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A, typename B> ostream& operator<<(ostream &stream, const map <A, B> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const set <A> &v) { stream << "["; for (auto itr = v.begin(); itr != v.end(); itr++)stream << *itr << " "; stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const priority_queue <A> &v) { priority_queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.top() << " "; q.pop(); }stream << "]"; return stream; }
template <typename A> ostream& operator<<(ostream &stream, const queue <A> &v) { queue <A> q = v; stream << "["; while (!q.empty()) { stream << q.front() << " "; q.pop(); }stream << "]"; return stream; }

//DBG
template<typename T, typename T2>void printarr(T  a[], T2 sz, T2 beg = 0) { for (T2 i = beg; i<sz; i++) cout << a[i] << " "; cout << endl; }
#define DBG(a)         cout<<#a<<"="<<(a)<<"\n"
#define DBG2(a,b)       cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<"\n"
#define DBG3(a,b,c)     cout<<#a<<"="<<(a)<<", "<<#b<<"="<<(b)<<", "<<#c<<"="<<(c)<<"\n"

//Files
#define FILE_MODE(FILE) freopen(FILE".in", "r", stdin), freopen(FILE".out", "w", stdout)

//Constants
#define PI    3.1415926535897932
#define INF   1011111111
#define LLINF 1000111000111000111LL
#define eps   1e-9
//-------------------------------------------------
#define N 100

bitset<((1 << 14) + 3)> a[(1 << 12) + 3];

string t[] = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000",
"1001", "1010", "1011", "1100", "1101", "1110", "1111" };

int p[(1 << 15) + 3], n, m;

int find(int x) {
	//cout << x << endl;
	if (p[x] == x)return x;
	return p[x] = find(p[x]);
}

bool merge(int a, int b) {
	int ind_a = find(a);
	int ind_b = find(b);
	if (ind_a == ind_b)return 0;
	p[ind_a] = ind_b;
	return 1;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> n >> m;
	rep(1, n + 1, i) {
		rep(0, m / 4, j) {
			char c;
			cin >> c;
			if (isalpha(c)) {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - 'A' + 10][z] - '0';
				}
			}
			else {
				rep(0, 4, z) {
					a[i][1 + j * 4 + z] = t[c - '0'][z] - '0';
				}
			}
		}
	}

	int cnt1 = 0, cntM = 0;

	rep(1, n + 1, i) {
		rep(1, m + 1, j) {
			p[j] = p[j + m] - m;
			p[j + m] = j + m;
		}

		rep(1, m + 1, j) {
			if (a[i][j] && a[i][j - 1]) {
				//cout << j << " " << j - 1 << " " << p[1][j] << " " << p[1][j - 1] << "; ";
				cntM += merge(j + m, j + m - 1);
			}
		}

		rep(1, m + 1, j) {
			if (a[i][j])cnt1++;
			if (a[i][j] && a[i - 1][j]) {
				cntM += merge(j, j + m);
			}
		}

	}

	cout << cnt1 - cntM << endl;

	return 0;
}

/*
10 4
E
8
A
E
3
F
F
C
F
3
*/


#include <iostream>
#include <vector>
#include <algorithm>
#include <math.h>
using namespace std;
typedef long long int lli;
int main(){
   lli n, sum1 = 0, sum2 = 0,temp,diff = 0,n_coins= 0;
   vector <lli> data;
   cin >> n;
   for(int i = 0; i < n; i++){
      cin >> temp;
      data.push_back(temp);
   }
   sort(data.begin(),data.end());
   for(int i = (n-1); i >= 0; i--){
      sum1 = sum1 + data[i];
      n_coins++;
      if(i != 0){
         sum2 = 0;
         for(int j = (i-1); j >= 0; j--){
            sum2 = sum2 + data[j];
         }
         diff = abs(sum2-sum1);
         if(diff == 0 || diff < data[0]){
            n_coins++;
            break;
         }
     }
   }
  cout << n_coins << endl;
}


#include <iostream>
#define MAX 101

using namespace std;

void swap(int i,int j, int *a){
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
void quicksort(int *arr, int left, int right){
    int min = (left+right)/2;

    int i = left;
    int j = right;
    int pivot = arr[min];

    while(left<j || i<right)
    {
        while(arr[i]<pivot)
        i++;
        while(arr[j]>pivot)
        j--;

        if(i<=j){
            swap(i,j,arr);
            i++;
            j--;
        }
        else{
            if(left<j)
                quicksort(arr, left, j);
            if(i<right)
                quicksort(arr,i,right);
            return;
        }
    }
}

int main()
{
    int n;
    int a[MAX];
    int b[MAX];
    int c[MAX];

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> a[i];
    }

    quicksort(a, 0, n - 1);

    b[0] = a[0];
    c[n - 1] = a[n - 1];

    for(int i = 1; i < n; i++)
    {
        b[i] = a[i] + b[i - 1];
        c[n - i - 1] = a[n - i - 1] + c[n - i];
    }

    int j = 0;
    while(b[j] < c[n - j - 1] && j < n / 2)
        j++;

    if(j == 0)
        j = n;

    cout << j << endl;

    return 0;
}


#include <iostream>
#define MAX 101

using namespace std;

void swap(int i,int j, int *a){
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
void quicksort(int *arr, int left, int right){
    int min = (left+right)/2;

    int i = left;
    int j = right;
    int pivot = arr[min];

    while(left<j || i<right)
    {
        while(arr[i]<pivot)
        i++;
        while(arr[j]>pivot)
        j--;

        if(i<=j){
            swap(i,j,arr);
            i++;
            j--;
        }
        else{
            if(left<j)
                quicksort(arr, left, j);
            if(i<right)
                quicksort(arr,i,right);
            return;
        }
    }
}

int main()
{
    int n;
    int a[MAX];
    int b[MAX];
    int c[MAX];

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> a[i];
    }

    quicksort(a, 0, n - 1);

    b[0] = a[0];
    c[n - 1] = a[n - 1];

    for(int i = 1; i < n; i++)
    {
        b[i] = a[i] + b[i - 1];
        c[n - i - 1] = a[n - i - 1] + c[n - i];
    }

    int j = 0;
    while(b[j] < c[n - j - 1] && j <= n / 2)
        j++;

    if(j == 0)
        j = n;

    cout << j << endl;

    return 0;
}


#include <iostream>
#define MAX 101

using namespace std;

void swap(int i,int j, int *a){
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
void quicksort(int *arr, int left, int right){
    int min = (left+right)/2;

    int i = left;
    int j = right;
    int pivot = arr[min];

    while(left<j || i<right)
    {
        while(arr[i]<pivot)
        i++;
        while(arr[j]>pivot)
        j--;

        if(i<=j){
            swap(i,j,arr);
            i++;
            j--;
        }
        else{
            if(left<j)
                quicksort(arr, left, j);
            if(i<right)
                quicksort(arr,i,right);
            return;
        }
    }
}

int main()
{
    int n;
    int a[MAX];
    int b[MAX];
    int c[MAX];

    cin >> n;
    for(int i = 0; i < n; i++)
        cin >> a[i];

    quicksort(a, 0, n - 1);

    b[0] = a[0];
    c[n - 1] = a[n - 1];

    for(int i = 1; i < n - 1; i++)
    {
        b[i] = a[i] + b[i - 1];
        c[n - i - 1] = a[n - i - 1] + c[n - i];
    }

    int i = 0;
    int j = n - 1;

    while(i < j)
    {
        while(c[j] > b[i])
            i++;
        if(i == j - 1)
        {
            cout << n - i << endl;
            return 0;
        }
        else
        {
            j--;
            i = 0;
        }
    }

    return 0;
}


#include <bits/stdc++.h>
#define MAX 101

using namespace std;

int main()
{
    int n;
    int *a = new int[MAX];
    int s = 0;

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> a[i];
        s += a[i];
    }

    sort(a, a + n);

    int j = 0, s2 = 0;
    while(s2 <= (int)s / 2)
    {
        s2 += a[n - j];
        j++;
    }

    cout << j - 1 << endl;

    return 0;
}


#include <bits/stdc++.h>
#define MAX 101

using namespace std;

int main()
{
    int n;
    int a[MAX];
    int s = 0;

    cin >> n;
    for(int i = 0; i < n; i++)\
    {
        cin >> a[i];
        s += a[i];
    }

    sort(a, a + n);

    int j = 0, s2 = 0;
    while(s2 <= (int)s / 2)
    {
        s2 += a[n - j];
        j++;
    }

    cout << j - 1 << endl;

    return 0;
}


#include <cstdio>
#include <algorithm>
using namespace std;

int main(){
    int numCoins; scanf("%d\n",&numCoins);  int *coins = new int[numCoins];
    long total = 0, outputCoins = 0, outputValue = 0;
    for(int k = 0; k < numCoins; k++){scanf("%d", coins + k); total += coins[k];}
    sort(coins, coins + numCoins);
    while(outputValue <= total / 2){++outputCoins; outputValue += coins[numCoins - outputCoins];}
    printf("%ld\n",outputCoins);
    return 0;
}


#include <bits/stdc++.h>
#define MAX 101

using namespace std;

int main()
{
    int n;
    int a[MAX];
    int s = 0;

    cin >> n;
    for(int i = 0; i < n; i++)\
    {
        cin >> a[i];
        s += a[i];
    }

    sort(a, a + n);

    int j = 0, s2 = 0;
    while(s2 <= s / 2)
    {
        s2 += a[n - j];
        j++;
    }

    cout << j - 1 << endl;

    return 0;
}


#include <iostream>
#define MAX 101

using namespace std;

void swap(int i,int j, int *a){
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
void quicksort(int *arr, int left, int right){
    int min = (left+right)/2;

    int i = left;
    int j = right;
    int pivot = arr[min];

    while(left<j || i<right)
    {
        while(arr[i]<pivot)
        i++;
        while(arr[j]>pivot)
        j--;

        if(i<=j){
            swap(i,j,arr);
            i++;
            j--;
        }
        else{
            if(left<j)
                quicksort(arr, left, j);
            if(i<right)
                quicksort(arr,i,right);
            return;
        }
    }
}

int main()
{
    int n;
    int a[MAX];
    int b[MAX];
    int c[MAX];
    long s = 0;

    cin >> n;
    for(int i = 0; i < n; i++)\
    {
        cin >> a[i];
        s += a[i];
    }

    quicksort(a, 0, n - 1);

    int j = 0, s2 = 0;
    while(s2 <= s / 2)
    {
        s2 += a[n - j];
        j++;
    }

    cout << j - 1 << endl;

    return 0;
}


#include <iostream>
#define MAX 101

using namespace std;

void swap(int i,int j, int *a){
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
void quicksort(int *arr, int left, int right){
    int min = (left+right)/2;

    int i = left;
    int j = right;
    int pivot = arr[min];

    while(left<j || i<right)
    {
        while(arr[i]<pivot)
        i++;
        while(arr[j]>pivot)
        j--;

        if(i<=j){
            swap(i,j,arr);
            i++;
            j--;
        }
        else{
            if(left<j)
                quicksort(arr, left, j);
            if(i<right)
                quicksort(arr,i,right);
            return;
        }
    }
}

int main()
{
    int n;
    int a[MAX];
    int b[MAX];
    int c[MAX];

    cin >> n;
    for(int i = 0; i < n; i++)
        cin >> a[i];

    if(n == 1)
    {
        cout << '1' << endl;
        return 0;
    }

    quicksort(a, 0, n - 1);

    b[0] = a[0];
    c[n - 1] = a[n - 1];

    for(int i = 1; i < n - 1; i++)
    {
        b[i] = a[i] + b[i - 1];
        c[n - i - 1] = a[n - i - 1] + c[n - i];
    }

    int i = 0;
    int j = n - 1;

    while(i < j)
    {
        while(c[j] > b[i])
            i++;
        if(i == j - 1)
        {
            cout << n - i << endl;
            return 0;
        }
        else
        {
            j--;
            i = 0;
        }
    }

    return 0;
}


#include <iostream>
#define MAX 101

using namespace std;

void swap(int i,int j, int *a){
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}
void quicksort(int *arr, int left, int right){
    int min = (left+right)/2;

    int i = left;
    int j = right;
    int pivot = arr[min];

    while(left<j || i<right)
    {
        while(arr[i]<pivot)
        i++;
        while(arr[j]>pivot)
        j--;

        if(i<=j){
            swap(i,j,arr);
            i++;
            j--;
        }
        else{
            if(left<j)
                quicksort(arr, left, j);
            if(i<right)
                quicksort(arr,i,right);
            return;
        }
    }
}

int main()
{
    int n;
    int a[MAX];
    int b[MAX];
    int c[MAX];

    cin >> n;
    for(int i = 0; i < n; i++)
    {
        cin >> a[i];
    }

    quicksort(a, 0, n - 1);

    b[0] = a[0];
    c[n - 1] = a[n - 1];

    for(int i = 1; i < n; i++)
    {
        b[i] = a[i] + b[i - 1];
        c[n - i - 1] = a[n - i - 1] + c[n - i];
    }

    int j = 0;
    while(b[j] < c[n - j - 1])
        j++;

    if(j == 0)
        j = n;

    cout << j << endl;

    return 0;
}


#include<iostream>
using namespace std;
int main()
{
    long long n,h=0,a;
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
    	cin>>a;
    	h+=a;
	}
	cout<<h/2+1;
	return 0;
}