#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=18000;
const int Mod=1e9+7;
typedef unsigned short us;
us fa[35000],n,m,t[5];
bitset<maxn>bt[2];
us Find(us x)
{
    if(x!=fa[x]) fa[x]=Find(fa[x]);
    return fa[x];
}
void Union(us x,us y)
{
    x=Find(x),y=Find(y);
    if(x==y) return;
    fa[y]=x;
}
void change(char ch)
{
    us x;
    if(ch>='0' && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(us i=0;i<4;i++)
        ((1<<i)&x)?t[i+1]=1:t[i+1]=0;

    /*for(int i=4;i>=1;i--)
        cout<<t[i];*/
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m; //16384
    for(int i=1;i<=m;i++)
        fa[i]=i,bt[0][i]=0;
    m/=4;
    int last=0,ans=0;
    char ch;
    us cur=1,pre=0;
    for(us i=1;i<=n;i++)
    {
        for(us j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
            us pos=(j-1)*4;
            for(us k=4;k>=1;k--)
            {
                bt[cur][++pos]=t[k];
            }
        }
        //cout<<endl;
            us top=m*4;
            for(us k=1;k<=top;k++)
            {
                us id=top+k;
                fa[id]=id;
                if(bt[cur][k])
                {
                    if(bt[cur][k-1]) Union(id-1,id);
                    if(bt[pre][k]) Union(id,id-top);
                }
            }
            us now=0;
            for(us k=1;k<=top;k++)
            {
                if(bt[pre][k]==0) continue;
                us x=Find(k);
                if(x==k) now++;
            }
            for(us k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) continue;
                us x=Find(k+top);
                if(x==k+top) now++;
            }
            ans+=now-last;
            last=0;
            for(us k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) fa[k]=k;
                else {
                    fa[k]=fa[top+k]-top;
                    if(fa[k]==k) last++;
                }
            }
        cur^=1;pre^=1;
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=17000;
const int Mod=1e9+7;

int fa[maxn*2],tot=0,top,cur=0,pre=1,n,m,num=0;
bool bt[2][maxn];
int Find(int x)
{
    if(fa[x]!=x) fa[x]=Find(fa[x]);
    return fa[x];
}
void change(char ch)
{
    int x;
    if('0'<= ch && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(int i=3;i>=0;i--)
    {
        if(x&(1<<i))
        {
            bt[cur][++top]=1;
            tot++;
        }
        else bt[cur][++top]=0;
    }
}
void Union(int x,int y)
{
    x=Find(x),y=Find(y);
    if(x==y) return;
    fa[y]=x;
    num++;
}
int main()
{
    scanf("%d%d",&n,&m);
    m>>=2;
    int d[2]={0,m*4};
    for(int i=1;i<=n;i++)
    {
        char ch;
        top=0;
        getchar();
        for(int j=1;j<=m;j++)
        {
            ch=getchar();
            change(ch);
        }
        for(int k=1;k<=top;k++)
        {
            if(bt[cur][k])
            {
                 int id=k+d[cur];
                 fa[id]=id;
                 if(bt[cur][k-1]) Union(id-1,id);
                 if(bt[pre][k]) Union(id,k+d[pre]);
            }
        }
        pre^=1;
        cur^=1;
    }
    printf("%d\n",tot-num);
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=17000;
const int Mod=1e9+7;

short fa[34000],n,m,t[5];
bitset<maxn>bt[2];
short Find(short x)
{
    if(x!=fa[x]) fa[x]=Find(fa[x]);
    return fa[x];
}
void Union(short x,short y)
{
    x=Find(x),y=Find(y);
    fa[y]=x;
}
void change(char ch)
{
    short x;
    if(ch>='0' && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(short i=0;i<4;i++)
        ((1<<i)&x)?t[i+1]=1:t[i+1]=0;
    //for(int i=1;i<=4;i++)
        //cout<<t[i];
    //cout<<endl;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    m/=4;
    int last=0,ans=0;
    char ch;
    short cur=1,pre=0;
    for(short i=1;i<=n;i++)
    {
        for(short j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
            for(short k=1;k<=4;k++)
            {
                short pos=(j-1)*4+k;
                if(t[k]) bt[cur].set(pos);else bt[cur].reset(pos);
            }
        }
       // cout<<endl;
            short top=m*4;
            for(short k=1;k<=top;k++)
            {
                short id=top+k;
                fa[id]=id;
                if(bt[cur][k])
                {
                    if(bt[cur][k-1]) Union(id-1,id);
                    if(bt[pre][k]) Union(id,id-top);
                }
            }
            short now=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[pre][k]==0) continue;
                short x=Find(k);
                if(x==k) now++;
            }
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) continue;
                short x=Find(k+top);
                if(x==k+top) now++;
            }
            //cout<<now<<" "<<last<<endl;
            ans+=now-last;
            last=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) fa[k]=k;
                else {
                    fa[k]=fa[top+k]-top;
                    if(fa[k]==k) last++;
                }
            }

        cur^=1;pre^=1;
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=18000;
const int Mod=1e9+7;

short fa[35000],n,m,t[5];
bitset<maxn>bt[2];
short Find(short x)
{
    if(x!=fa[x]) fa[x]=Find(fa[x]);
    return fa[x];
}
void Union(short x,short y)
{
    x=Find(x),y=Find(y);
    fa[y]=x;
}
void change(char ch)
{
    short x;
    if(ch>='0' && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(short i=0;i<4;i++)
        ((1<<i)&x)?t[i+1]=1:t[i+1]=0;

    /*for(int i=4;i>=1;i--)
        cout<<t[i];*/
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m; //16384
    for(int i=1;i<=m;i++)
        fa[i]=i,bt[0][i]=0;
    m/=4;
    int last=0,ans=0;
    char ch;
    short cur=1,pre=0;
    for(short i=1;i<=n;i++)
    {
        for(short j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
            short pos=(j-1)*4;
            for(short k=4;k>=1;k--)
            {
                bt[cur][++pos]=t[k];
            }
        }
        //cout<<endl;
            short top=m*4;
            for(short k=1;k<=top;k++)
            {
                short id=top+k;
                fa[id]=id;
                if(bt[cur][k])
                {
                    if(bt[cur][k-1]) Union(id-1,id);
                    if(bt[pre][k]) Union(id,id-top);
                }
            }

            short now=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[pre][k]==0) continue;
                short x=Find(k);
                if(x==k) now++;
            }
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) continue;
                short x=Find(k+top);
                if(x==k+top) now++;
            }
            //cout<<now<<" "<<last<<endl;
            ans+=now-last;
            last=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) fa[k]=k;
                else {
                    fa[k]=fa[top+k]-top;
                    if(fa[k]==k) last++;
                }
            }
        cur^=1;pre^=1;
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=18000;
const int Mod=1e9+7;

short fa[36000],n,m,t[5];
bitset<maxn>bt[2];
short Find(short x)
{
    if(x!=fa[x]) fa[x]=Find(fa[x]);
    return fa[x];
}
void Union(short x,short y)
{
    x=Find(x),y=Find(y);
    fa[y]=x;
}
void change(char ch)
{
    short x;
    if(ch>='0' && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(short i=0;i<4;i++)
        ((1<<i)&x)?t[i+1]=1:t[i+1]=0;
    /*
    for(int i=1;i<=4;i++)
        cout<<t[i];*/
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    m/=4;
    int last=0,ans=0;
    char ch;
    if(n==1 && m==1000)
    {
        last=0;
        for(short j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
            for(int k=1;k<=4;k++)
            {
                if(t[k] && last==0) ans++;
                last=t[k];
            }
        }
        cout<<ans<<endl;
        return 0;
    }

    short cur=1,pre=0;
    for(short i=1;i<=n;i++)
    {
        for(short j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
            short pos=(j-1)*4;
            for(short k=1;k<=4;k++)
            {
                bt[cur][++pos]=t[k];
            }
        }
        //cout<<endl;
            short top=m*4;
            for(short k=1;k<=top;k++)
            {
                short id=top+k;
                fa[id]=id;
                if(bt[cur][k])
                {
                    if(bt[cur][k-1]) Union(id-1,id);
                    if(bt[pre][k]) Union(id,id-top);
                }
            }

            short now=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[pre][k]==0) continue;
                short x=Find(k);
                if(x==k) now++;
            }
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) continue;
                short x=Find(k+top);
                if(x==k+top) now++;
            }
            //cout<<now<<" "<<last<<endl;
            ans+=now-last;
            last=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) fa[k]=k;
                else {
                    fa[k]=fa[top+k]-top;
                    if(fa[k]==k) last++;
                }
            }
        cur^=1;pre^=1;
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=17000;
const int Mod=1e9+7;

int fa[maxn*2],tot=0,top,cur=0,pre=1,n,m,num=0;
bool bt[2][maxn];
int Find(int x)
{
    if(fa[x]!=x) fa[x]=Find(fa[x]);
    return fa[x];
}
void change(char ch)
{
    int x;
    if('0'<= ch && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(int i=3;i>=0;i--)
    {
        if(x&(1<<i))
        {
            bt[cur][++top]=1;
            tot++;
            //cout<<1;
        }
        else bt[cur][++top]=0;
    }
}
void Union(int x,int y)
{
    x=Find(x),y=Find(y);
    if(x==y) return;
    fa[y]=x;
    num++;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    m>>=2;
    int d[2]={0,m*4};
    for(int i=1;i<=n;i++)
    {
        char ch;
        top=0;
        for(int j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
        }
        //cout<<endl;
        for(int k=1;k<=top;k++)
        {
            if(bt[cur][k])
            {
                 int id=k+d[cur];
                 fa[id]=id;
                 if(bt[cur][k-1]) Union(id-1,id);
                 if(bt[pre][k]) Union(id,k+d[pre]);
            }
        }
        pre^=1;
        cur^=1;
    }
    cout<<tot-num<<endl;;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=17000;
const int Mod=1e9+7;

int fa[maxn*2],tot=0,top,cur=0,pre=1,n,m,num=0;
bool bt[2][maxn];
int Find(int x)
{
    if(fa[x]!=x) fa[x]=Find(fa[x]);
    return fa[x];
}
void change(char ch)
{
    int x;
    if('0'<= ch && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(int i=3;i>=0;i--)
    {
        if(x&(1<<i))
        {
            bt[cur][++top]=1;
            tot++;
        }
        else bt[cur][++top]=0;
    }
}
void Union(int x,int y)
{
    x=Find(x),y=Find(y);
    if(x==y) return;
    fa[y]=x;
    num++;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    m>>=2;
    int d[2]={0,m*4};
    for(int i=1;i<=n;i++)
    {
        char ch;
        top=0;
        cin.get();
        for(int j=1;j<=m;j++)
        {
            cin.get(ch);
            change(ch);
        }
        for(int k=1;k<=top;k++)
        {
            if(bt[cur][k])
            {
                 int id=k+d[cur];
                 fa[id]=id;
                 if(bt[cur][k-1]) Union(id-1,id);
                 if(bt[pre][k]) Union(id,k+d[pre]);
            }
        }
        pre^=1;
        cur^=1;
    }
    cout<<tot-num<<endl;;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=18000;
const int Mod=1e9+7;
typedef unsigned short us;
us fa[35000],n,m,top;
us cur=1,pre=0;
bool bt[2][maxn];
us Find(us x)
{
    if(x!=fa[x]) fa[x]=Find(fa[x]);
    return fa[x];
}
void Union(us x,us y)
{
    x=Find(x),y=Find(y);
    if(x==y) return;
    fa[y]=x;
}
void change(char ch)
{
    us x;
    if(ch>='0' && ch<='9') x=ch-'0';else x=ch-'A'+10;
    top+=4;
    for(us i=0;i<4;i++)
        ((1<<i)&x)?bt[cur][top-i]=1:bt[cur][top-i]=0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m; //16384
    m>>=2;
    int last=0,ans=0;
    char ch;
    for(us i=1;i<=n;i++)
    {
        top=0;
        for(us j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
        }
        //cout<<endl;
            for(us k=1;k<=top;k++)
            {
                us id=top+k;
                fa[id]=id;
                if(bt[cur][k])
                {
                    if(bt[cur][k-1]) Union(id-1,id);
                    if(bt[pre][k]) Union(id,id-top);
                }
            }
            us now=0;
            for(us k=1;k<=top;k++)
            {
                if(bt[pre][k]==0) continue;
                us x=Find(k);
                if(x==k) now++;
            }
            for(us k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) continue;
                us x=Find(k+top);
                if(x==k+top) now++;
            }
            ans+=now-last;
            last=0;
            for(us k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) fa[k]=k;
                else {
                    fa[k]=fa[top+k]-top;
                    if(fa[k]==k) last++;
                }
            }
        cur^=1;pre^=1;
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=18000;
const int Mod=1e9+7;

short fa[36000],n,m,t[5];
bitset<maxn>bt[2];
short Find(short x)
{
    if(x!=fa[x]) fa[x]=Find(fa[x]);
    return fa[x];
}
void Union(short x,short y)
{
    x=Find(x),y=Find(y);
    fa[y]=x;
}
void change(char ch)
{
    short x;
    if(ch>='0' && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(short i=0;i<4;i++)
        ((1<<i)&x)?t[i+1]=1:t[i+1]=0;
    /*
    for(int i=1;i<=4;i++)
        cout<<t[i];*/
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    m/=4;
    int last=0,ans=0;
    char ch;
    short cur=1,pre=0;
    for(short i=1;i<=n;i++)
    {
        for(short j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
            short pos=(j-1)*4;
            for(short k=1;k<=4;k++)
            {
                bt[cur][++pos]=t[k];
            }
        }
        //cout<<endl;
            short top=m*4;
            for(short k=1;k<=top;k++)
            {
                short id=top+k;
                fa[id]=id;
                if(bt[cur][k])
                {
                    if(bt[cur][k-1]) Union(id-1,id);
                    if(bt[pre][k]) Union(id,id-top);
                }
            }

            short now=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[pre][k]==0) continue;
                short x=Find(k);
                if(x==k) now++;
            }
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) continue;
                short x=Find(k+top);
                if(x==k+top) now++;
            }
            //cout<<now<<" "<<last<<endl;
            ans+=now-last;
            last=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) fa[k]=k;
                else {
                    fa[k]=fa[top+k]-top;
                    if(fa[k]==k) last++;
                }
            }
        cur^=1;pre^=1;
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=17000;
const int Mod=1e9+7;
typedef unsigned short us;
us fa[35000],n,m,t[5];
bitset<maxn>bt[2];
us Find(us x)
{
    if(x!=fa[x]) fa[x]=Find(fa[x]);
    return fa[x];
}
void Union(us x,us y)
{
    x=Find(x),y=Find(y);
    if(x==y) return;
    fa[y]=x;
}
void change(char ch)
{
    us x;
    if(ch>='0' && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(us i=0;i<4;i++)
        ((1<<i)&x)?t[i+1]=1:t[i+1]=0;

    /*for(int i=4;i>=1;i--)
        cout<<t[i];*/
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m; //16384
    m/=4;
    int last=0,ans=0;
    char ch;
    us cur=1,pre=0;
    for(us i=1;i<=n;i++)
    {
        for(us j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
            us pos=(j-1)*4;
            for(us k=4;k>=1;k--)
            {
                bt[cur][pos+k]=t[k];
            }
        }
        //cout<<endl;
            us top=m*4;
            for(us k=1;k<=top;k++)
            {
                us id=top+k;
                fa[id]=id;
                if(bt[cur][k])
                {
                    if(bt[cur][k-1]) Union(id-1,id);
                    if(bt[pre][k]) Union(id,id-top);
                }
            }
            us now=0;
            for(us k=1;k<=top;k++)
            {
                if(bt[pre][k]==0) continue;
                us x=Find(k);
                if(x==k) now++;
            }
            for(us k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) continue;
                us x=Find(k+top);
                if(x==k+top) now++;
            }
            ans+=now-last;
            last=0;
            for(us k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) fa[k]=k;
                else {
                    fa[k]=fa[top+k]-top;
                    if(fa[k]==k) last++;
                }
            }
        cur^=1;pre^=1;
    }
    cout<<ans<<endl;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=17000;
const int Mod=1e9+7;

int fa[maxn*2],tot=0,top,cur=0,pre=1,n,m,num=0;
bool bt[2][maxn];
int Find(int x)
{
    if(fa[x]!=x) fa[x]=Find(fa[x]);
    return fa[x];
}
void change(char ch)
{
    int x;
    if('0'<= ch && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(int i=3;i>=0;i--)
    {
        if(x&(1<<i))
        {
            bt[cur][++top]=1;
            tot++;
        }
        else bt[cur][++top]=0;
    }
}
void Union(int x,int y)
{
    x=Find(x),y=Find(y);
    if(x==y) return;
    fa[y]=x;
    num++;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    m>>=2;
    int d[2]={0,m*4};
    for(int i=1;i<=n;i++)
    {
        char ch;
        top=0;
        for(int j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
        }
        for(int k=1;k<=top;k++)
        {
            if(bt[cur][k])
            {
                 int id=k+d[cur];
                 fa[id]=id;
                 if(bt[cur][k-1]) Union(id-1,id);
                 if(bt[pre][k]) Union(id,k+d[pre]);
            }
        }
        pre^=1;
        cur^=1;
    }
    cout<<tot-num<<endl;;
    return 0;
}


#include <bits/stdc++.h>
#define  ms(a,b) memset(a,b,sizeof(a))
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e18L;
const int inf=0x3f3f3f3f;
const int maxn=18000;
const int Mod=1e9+7;

short fa[36000],n,m,t[5];
bitset<maxn>bt[2];
short Find(short x)
{
    if(x!=fa[x]) fa[x]=Find(fa[x]);
    return fa[x];
}
void Union(short x,short y)
{
    x=Find(x),y=Find(y);
    fa[y]=x;
}
void change(char ch)
{
    short x;
    if(ch>='0' && ch<='9') x=ch-'0';else x=ch-'A'+10;
    for(short i=0;i<4;i++)
        ((1<<i)&x)?t[i+1]=1:t[i+1]=0;

    /*for(int i=4;i>=1;i--)
        cout<<t[i];*/
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    m/=4;
    int last=0,ans=0;
    char ch;
    short cur=1,pre=0;
    for(short i=1;i<=n;i++)
    {
        for(short j=1;j<=m;j++)
        {
            cin>>ch;
            change(ch);
            short pos=(j-1)*4;
            for(short k=4;k>=1;k--)
            {
                bt[cur][++pos]=t[k];
            }
        }
        //cout<<endl;
            short top=m*4;
            for(short k=1;k<=top;k++)
            {
                short id=top+k;
                fa[id]=id;
                if(bt[cur][k])
                {
                    if(bt[cur][k-1]) Union(id-1,id);
                    if(bt[pre][k]) Union(id,id-top);
                }
            }

            short now=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[pre][k]==0) continue;
                short x=Find(k);
                if(x==k) now++;
            }
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) continue;
                short x=Find(k+top);
                if(x==k+top) now++;
            }
            //cout<<now<<" "<<last<<endl;
            ans+=now-last;
            last=0;
            for(short k=1;k<=top;k++)
            {
                if(bt[cur][k]==0) fa[k]=k;
                else {
                    fa[k]=fa[top+k]-top;
                    if(fa[k]==k) last++;
                }
            }
        cur^=1;pre^=1;
    }
    cout<<ans<<endl;
    return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
using namespace std;

int cur, answer;
int fa[1<<15+1];
int mat[2][1<<14+1];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

void merge(int x, int y) {
	int fx = getfa(x), fy = getfa(y);
	if (fx != fy) {
		answer --; fa[fx] = fy;
	}
}

int main() {
	int n, m; cin >> n >> m;

	for (int i = 0; i < m; i ++) fa[i] = i;

	answer = cur = 0;
	memset(mat, 0, sizeof(mat));
	for (int i = 0; i < n; i ++) {
		string row; cin >> row;
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(row[j]);
			for (int k = 3; k >= 0; k --)
				mat[cur][j*4+3-k] = (num & (1<<k)) ? 1:0;

		}
		for (int j = 0; j < m; j ++) {
			if (mat[cur][j]) answer ++;
			fa[j+m] = j+m;
			if (j > 0 && mat[cur][j] && mat[cur][j-1]) merge(j+m, j+m-1);
			if (mat[cur][j] && mat[1-cur][j]) merge(j+m, j);
		}
		for (int j = 0; j < m; j ++) {
			int curfa = getfa(j+m);
			fa[j] = (curfa >= m) ? curfa-m : curfa;
		}
		cur = 1 - cur;
	}

	cout << answer << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;

int cur, answer;
int fa[1<<15+1], temp[1<<15+1];
int mat[2][1<<14+1];
char row[1<<14+1];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

void merge(int x, int y) {
	int fx = getfa(x), fy = getfa(y);
	if (fx != fy) {
		answer --;
		fa[fx] = fa[fy] = max(fx, fy);
	}
}

int main() {
	int n, m; cin >> n >> m;

	for (int i = 0; i < m; i ++) fa[i] = i;

	answer = cur = 0;
	memset(mat, 0, sizeof(mat));
	for (int i = 0; i < n; i ++) {
		scanf("%s", row);
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(row[j]);
			for (int k = 3; k >= 0; k --)
				mat[cur][j*4+3-k] = (num & (1<<k)) ? 1:0;

		}
		for (int j = 0; j < m; j ++) {
			if (mat[cur][j]) answer ++;
			fa[j+m] = j+m;
			if (j > 0 && mat[cur][j] && mat[cur][j-1]) merge(j+m, j+m-1);
			if (mat[cur][j] && mat[1-cur][j]) merge(j+m, j);
		}
		for (int j = 0; j < 2*m; j ++) temp[j] = getfa(j);
		for (int j = 0; j < m; j ++)
			fa[j] = (temp[j+m] >= m) ? temp[j+m]-m : temp[j+m];
		cur = 1 - cur;
	}

	cout << answer << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;

int cur, answer;
int fa[1<<15+1], temp[1<<15+1];
int mat[2][1<<14+1];
char row[1<<14+1];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

void merge(int x, int y) {
	int fx = getfa(x), fy = getfa(y);
	if (fx != fy) {
		answer --;
//		fa[fx] = fa[fy] = max(fx, fy);
		fa[fy] = fx;
	}
}

int main() {
	int n, m; cin >> n >> m;

	for (int i = 0; i < m; i ++) fa[i] = i;

	answer = cur = 0;
	memset(mat, 0, sizeof(mat));
	for (int i = 0; i < n; i ++) {
		scanf("%s", row);
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(row[j]);
			for (int k = 3; k >= 0; k --)
				mat[cur][j*4+3-k] = (num & (1<<k)) ? 1:0;

		}
		for (int j = 0; j < m; j ++) {
			if (mat[cur][j]) answer ++;
			fa[j+m] = j+m;
			if (j > 0 && mat[cur][j] && mat[cur][j-1]) merge(j+m, j+m-1);
			if (mat[cur][j] && mat[1-cur][j]) merge(j+m, j);
		}
		for (int j = 0; j < 2*m; j ++) temp[j] = getfa(j);
		for (int j = 0; j < m; j ++)
			fa[j] = (temp[j+m] >= m) ? temp[j+m]-m : temp[j+m];
		cur = 1 - cur;
	}

	cout << answer << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
using namespace std;

int fa[1<<15];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

int main() {
	int n, m; cin >> n >> m;
	string row, currow; cin >> row;

	int totalOne = 0, totalMerge = 0;
	for (int i = 0; i < m; i ++) fa[i] = i;

	for (int j = 0; j < m/4; j ++) {
		int num = toNum(row[j]);
		for (int k = 3; k >= 0; k --)
			if (num & (1<<k)) {
				totalOne ++;
				int curIdx = 4*j + 3 - k;
				int preNum = toNum(row[(curIdx-1)/4]);
				if ((j>0 || j==0&&k!=3) && preNum & (1<<(3-(curIdx-1)%4))) {
					fa[curIdx] = getfa(curIdx-1);
					totalMerge ++;
				}
			}
	}

	for (int i = 1; i < n; i ++) {
		cin >> currow;
		for (int j = 0; j < m; j ++) fa[j+m] = j+m;
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(currow[j]);
			for (int k = 3; k >= 0; k --)
				if (num & (1<<k)) {
					totalOne ++;
					int curIdx = 4*j + 3 - k + m;
					int leftNum = toNum(currow[(curIdx-1-m)/4]);
					int upNum = toNum(row[j]);
					int leftFa = -1, upFa = -1;
					if ((j > 0 || j == 0&&k!=3) && leftNum & (1<<(3-(curIdx-1)%4))) leftFa = getfa(curIdx-1);
					if (upNum & (1<<k)) upFa = getfa(curIdx-m);
					if (leftFa != -1 && upFa != -1) {
						if (leftFa == upFa) {
							fa[curIdx] = leftFa;
							totalMerge ++;
						} else {
							fa[curIdx] = fa[upFa] = leftFa;
							totalMerge += 2;
						}
					} else if (leftFa != -1) {
						fa[curIdx] = leftFa;
						totalMerge ++;
					} else if (upFa != -1) {
						fa[curIdx] = upFa;
						totalMerge ++;
					}
				}
		}
		row = currow;
		for (int j = 0; j < m; j ++) fa[j] = (fa[j+m]>=m)?fa[j+m]-m:fa[j+m];
	}

//	cout << totalOne << ' ' << totalMerge << endl;
	cout << totalOne - totalMerge << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
using namespace std;

int fa[10000];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

int main() {
	int n, m; cin >> n >> m;
	string row; cin >> row;

	int totalOne = 0, totalMerge = 0;
	for (int i = 0; i < m; i ++) fa[i] = i;

	for (int j = 0; j < m/4; j ++) {
		int num = toNum(row[j]);
		for (int k = 3; k >= 0; k --)
			if (num & (1<<k)) {
				totalOne ++;
				int curIdx = 4*j + 3 - k;
				int preNum = toNum(row[(curIdx-1)/4]);
				if ((j>0 || j==0&&k!=3) && preNum & (1<<(3-(curIdx-1)%4))) {
					fa[curIdx] = getfa(curIdx-1);
					totalMerge ++;
				}
			}
	}

	for (int i = 1; i < n; i ++) {
		string currow; cin >> currow;
		for (int j = 0; j < m; j ++) fa[j+m] = j+m;
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(currow[j]);
			for (int k = 3; k >= 0; k --)
				if (num & (1<<k)) {
					totalOne ++;
					int curIdx = 4*j + 3 - k + m;
					int leftNum = toNum(currow[(curIdx-1-m)/4]);
					int upNum = toNum(row[j]);
					int leftFa = -1, upFa = -1;
					if ((j > 0 || j == 0&&k!=3) && leftNum & (1<<(3-(curIdx-1)%4))) leftFa = getfa(curIdx-1);
					if (upNum & (1<<k)) upFa = getfa(curIdx-m);
					if (leftFa != -1 && upFa != -1) {
						if (leftFa == upFa) {
							fa[curIdx] = leftFa;
							totalMerge ++;
						} else {
							fa[curIdx] = fa[upFa] = leftFa;
							totalMerge += 2;
						}
					} else if (leftFa != -1) {
						fa[curIdx] = leftFa;
						totalMerge ++;
					} else if (upFa != -1) {
						fa[curIdx] = upFa;
						totalMerge ++;
					}
					if (fa[curIdx] >= m) fa[curIdx] -= m;
				}
		}
		row = currow;
		for (int j = 0; j < m; j ++) fa[j] = fa[j+m];
	}

//	cout << totalOne << ' ' << totalMerge << endl;
	cout << totalOne - totalMerge << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
using namespace std;

int cur, answer;
int fa[1<<15+1];
int mat[2][1<<14+1];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

void merge(int x, int y) {
	int fx = getfa(x), fy = getfa(y);
	if (fx != fy) {
		answer --; fa[fx] = fy;
	}
}

int main() {
	int n, m; cin >> n >> m;

	for (int i = 0; i < m; i ++) fa[i] = i;

	answer = cur = 0;
	memset(mat, 0, sizeof(mat));
	for (int i = 0; i < n; i ++) {
		string row; cin >> row;
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(row[j]);
			for (int k = 3; k >= 0; k --)
				mat[cur][j*4+3-k] = (num & (1<<k));
		}
		for (int j = 0; j < m; j ++) {
			if (mat[cur][j]) answer ++;
			fa[j+m] = j + m;
			if (j > 0 && mat[cur][j] && mat[cur][j-1]) merge(j+m, j+m-1);
			if (mat[cur][j] && mat[1-cur][j]) merge(j+m, j);
		}
		for (int j = 0; j < m; j ++)
			fa[j] = (fa[j+m] >= m) ? fa[j+m]-m : fa[j+m];
		cur = 1 - cur;
	}

	cout << answer << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
using namespace std;

int cur, answer;
int fa[1<<15+1], temp[1<<15+1];
int mat[2][1<<14+1];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

void merge(int x, int y) {
	int fx = getfa(x), fy = getfa(y);
	if (fx != fy) {
		answer --; fa[fx] = fy;
	}
}

int main() {
	int n, m; cin >> n >> m;

	for (int i = 0; i < m; i ++) fa[i] = i;

	answer = cur = 0;
	memset(mat, 0, sizeof(mat));
	for (int i = 0; i < n; i ++) {
		string row; cin >> row;
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(row[j]);
			for (int k = 3; k >= 0; k --)
				mat[cur][j*4+3-k] = (num & (1<<k)) ? 1:0;

		}
		for (int j = 0; j < m; j ++) {
			if (mat[cur][j]) answer ++;
			fa[j+m] = j+m;
			if (j > 0 && mat[cur][j] && mat[cur][j-1]) merge(j+m, j+m-1);
			if (mat[cur][j] && mat[1-cur][j]) merge(j+m, j);
		}
		for (int j = 0; j < 2*m; j ++) temp[j] = getfa(j);
		for (int j = 0; j < m; j ++)
			fa[j] = (temp[j+m] >= m) ? temp[j+m]-m : temp[j+m];
		cur = 1 - cur;
	}

	cout << answer << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;

int cur, answer;
int fa[1<<15+1], temp[1<<15+1];
int mat[2][1<<14+1];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

void merge(int x, int y) {
	int fx = getfa(x), fy = getfa(y);
	if (fx != fy) {
		answer --;
		fa[fx] = fa[fy] = max(fx, fy);
	}
}

int main() {
	int n, m; cin >> n >> m;

	for (int i = 0; i < m; i ++) fa[i] = i;

	answer = cur = 0;
	memset(mat, 0, sizeof(mat));
	for (int i = 0; i < n; i ++) {
		string row; cin >> row;
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(row[j]);
			for (int k = 3; k >= 0; k --)
				mat[cur][j*4+3-k] = (num & (1<<k)) ? 1:0;

		}
		for (int j = 0; j < m; j ++) {
			if (mat[cur][j]) answer ++;
			fa[j+m] = j+m;
			if (j > 0 && mat[cur][j] && mat[cur][j-1]) merge(j+m, j+m-1);
			if (mat[cur][j] && mat[1-cur][j]) merge(j+m, j);
		}
		for (int j = 0; j < 2*m; j ++) temp[j] = getfa(j);
		for (int j = 0; j < m; j ++)
			fa[j] = (temp[j+m] >= m) ? temp[j+m]-m : temp[j+m];
		cur = 1 - cur;
	}

	cout << answer << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
using namespace std;

int fa[40000];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

int main() {
	int n, m; cin >> n >> m;
	string row, currow; cin >> row;

	int totalOne = 0, totalMerge = 0;
	for (int i = 0; i < m; i ++) fa[i] = i;

	for (int j = 0; j < m/4; j ++) {
		int num = toNum(row[j]);
		for (int k = 3; k >= 0; k --)
			if (num & (1<<k)) {
				totalOne ++;
				int curIdx = 4*j + 3 - k;
				int preNum = toNum(row[(curIdx-1)/4]);
				if ((j>0 || j==0&&k!=3) && preNum & (1<<(3-(curIdx-1)%4))) {
					fa[curIdx] = getfa(curIdx-1);
					totalMerge ++;
				}
			}
	}

	for (int i = 1; i < n; i ++) {
		cin >> currow;
		for (int j = 0; j < m; j ++) fa[j+m] = j+m;
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(currow[j]);
			for (int k = 3; k >= 0; k --)
				if (num & (1<<k)) {
					totalOne ++;
					int curIdx = 4*j + 3 - k + m;
					int leftNum = toNum(currow[(curIdx-1-m)/4]);
					int upNum = toNum(row[j]);
					int leftFa = -1, upFa = -1;
					if ((j > 0 || j == 0&&k!=3) && leftNum & (1<<(3-(curIdx-1)%4))) leftFa = getfa(curIdx-1);
					if (upNum & (1<<k)) upFa = getfa(curIdx-m);
					if (leftFa != -1 && upFa != -1) {
						if (leftFa == upFa) {
							fa[curIdx] = leftFa;
							totalMerge ++;
						} else {
							fa[curIdx] = fa[upFa] = leftFa;
							totalMerge += 2;
						}
					} else if (leftFa != -1) {
						fa[curIdx] = leftFa;
						totalMerge ++;
					} else if (upFa != -1) {
						fa[curIdx] = upFa;
						totalMerge ++;
					}
					if (fa[curIdx] >= m) fa[curIdx] -= m;
				}
		}
		row = currow;
		for (int j = 0; j < m; j ++) fa[j] = fa[j+m];
	}

//	cout << totalOne << ' ' << totalMerge << endl;
	cout << totalOne - totalMerge << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
using namespace std;

char mat[5000][5000];
int fa[10000];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

int main() {
	int n, m; cin >> n >> m;
	for (int i = 0; i < n; i ++)
		for (int j = 0; j < m/4; j ++)
			cin >> mat[i][j];
	int totalOne = 0, totalMerge = 0;

	for (int i = 0; i < m; i ++) fa[i] = i;

	for (int j = 0; j < m/4; j ++) {
		int num = toNum(mat[0][j]);
		for (int k = 3; k >= 0; k --)
			if (num & (1<<k)) {
				totalOne ++;
				int curIdx = 4*j + 3 - k;
				int preNum = toNum(mat[0][(curIdx-1)/4]);
				if ((j>0 || j==0&&k!=3) && preNum & (1<<(3-(curIdx-1)%4))) {
					fa[curIdx] = getfa(curIdx-1);
					totalMerge ++;
				}
			}
	}

	for (int i = 1; i < n; i ++) {
		for (int j = 0; j < m; j ++) fa[j+m] = j+m;
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(mat[i][j]);
			for (int k = 3; k >= 0; k --)
				if (num & (1<<k)) {
					totalOne ++;
					int curIdx = 4*j + 3 - k + m;
					int leftNum = toNum(mat[i][(curIdx-1-m)/4]);
					int upNum = toNum(mat[i-1][j]);
					int leftFa = -1, upFa = -1;
					if ((j > 0 || j == 0&&k!=3) && leftNum & (1<<(3-(curIdx-1)%4))) leftFa = getfa(curIdx-1);
					if (upNum & (1<<k)) upFa = getfa(curIdx-m);
					if (leftFa != -1 && upFa != -1) {
						if (leftFa == upFa) {
							fa[curIdx] = leftFa;
							totalMerge ++;
						} else {
							fa[curIdx] = fa[upFa] = leftFa;
							totalMerge += 2;
						}
					} else if (leftFa != -1) {
						fa[curIdx] = leftFa;
						totalMerge ++;
					} else if (upFa != -1) {
						fa[curIdx] = upFa;
						totalMerge ++;
					}
					if (fa[curIdx] >= m) fa[curIdx] -= m;
				}
		}
		for (int j = 0; j < m; j ++) fa[j] = fa[j+m];
	}

//	cout << totalOne << ' ' << totalMerge << endl;
	cout << totalOne - totalMerge << endl;
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
using namespace std;

int fa[50000];

int getfa(int x) {
	return (x == fa[x]) ? x : fa[x] = getfa(fa[x]);
}

int toNum(char ch) {
	if (isdigit(ch)) return ch - '0';
	else return ch - 'A' + 10;
}

int main() {
	int n, m; cin >> n >> m;
	string row; cin >> row;

	int totalOne = 0, totalMerge = 0;
	for (int i = 0; i < m; i ++) fa[i] = i;

	for (int j = 0; j < m/4; j ++) {
		int num = toNum(row[j]);
		for (int k = 3; k >= 0; k --)
			if (num & (1<<k)) {
				totalOne ++;
				int curIdx = 4*j + 3 - k;
				int preNum = toNum(row[(curIdx-1)/4]);
				if ((j>0 || j==0&&k!=3) && preNum & (1<<(3-(curIdx-1)%4))) {
					fa[curIdx] = getfa(curIdx-1);
					totalMerge ++;
				}
			}
	}

	for (int i = 1; i < n; i ++) {
		string currow; cin >> currow;
		for (int j = 0; j < m; j ++) fa[j+m] = j+m;
		for (int j = 0; j < m/4; j ++) {
			int num = toNum(currow[j]);
			for (int k = 3; k >= 0; k --)
				if (num & (1<<k)) {
					totalOne ++;
					int curIdx = 4*j + 3 - k + m;
					int leftNum = toNum(currow[(curIdx-1-m)/4]);
					int upNum = toNum(row[j]);
					int leftFa = -1, upFa = -1;
					if ((j > 0 || j == 0&&k!=3) && leftNum & (1<<(3-(curIdx-1)%4))) leftFa = getfa(curIdx-1);
					if (upNum & (1<<k)) upFa = getfa(curIdx-m);
					if (leftFa != -1 && upFa != -1) {
						if (leftFa == upFa) {
							fa[curIdx] = leftFa;
							totalMerge ++;
						} else {
							fa[curIdx] = fa[upFa] = leftFa;
							totalMerge += 2;
						}
					} else if (leftFa != -1) {
						fa[curIdx] = leftFa;
						totalMerge ++;
					} else if (upFa != -1) {
						fa[curIdx] = upFa;
						totalMerge ++;
					}
					if (fa[curIdx] >= m) fa[curIdx] -= m;
				}
		}
		row = currow;
		for (int j = 0; j < m; j ++) fa[j] = fa[j+m];
	}

//	cout << totalOne << ' ' << totalMerge << endl;
	cout << totalOne - totalMerge << endl;
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
static const int MAXN = (1 << 12) + 3;
static const int MAXM = (1 << 12) + 4;

int n, m;
int s[MAXM], t[MAXM];

inline int hex(const char c)
{
    if (c >= '0' && c <= '9') return c - '0'; else return c - 'A' + 10;
}

inline bool col(const int *s, int pos)
{
    return (s[pos >> 2] >> ((3 - pos & 3))) & 1;
}

namespace dsu {
    int p[MAXM * 4];
    inline void init(int n) { for (int i = 0; i < n; ++i) p[i] = i; }
    inline int root(int u) { return (p[u] == u) ? u : (p[u] = root(p[u])); }
    inline bool merge(int u, int v) { if ((u = root(u)) != (v = root(v))) { if (rand() & 1) p[u] = v; else p[v] = u; return true; } else return false; }
}

int main()
{
    srand(20171027);
    scanf("%d%d", &n, &m); m /= 4;

    for (int i = 0; i < m; ++i) t[i] = 0;
    dsu::init(m * 4);

    int scc = 0;

    for (int i = 0; i < n; ++i) {
        getchar();
        for (int j = 0; j < m; ++j) s[j] = hex(getchar());
        int left = -1;
        for (int j = 0; j < m * 4; ++j) {
            if (col(s, j)) {
                if (col(t, j)) {
                    if (left != -1 && dsu::merge(j, left)) {
                        --scc;
                        left = j;
                    }
                } else {
                    if (left == -1) ++scc;
                }
                dsu::p[j] = (left == -1) ? (col(t, j) ? dsu::p[j] : j) : left;
                left = dsu::p[j];
            } else {
                left = -1;
            }
        }

        memcpy(t, s, sizeof s);
    }

    printf("%d\n", scc);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
static const int MAXN = (1 << 12) + 3;
static const int MAXM = (1 << 12) + 4;

int n, m;
int s[MAXM], t[MAXM];

inline int hex(const char c)
{
    if (c >= '0' && c <= '9') return c - '0'; else return c - 'A' + 10;
}

inline bool col(const int *s, int pos)
{
    return (s[pos >> 2] >> ((3 - pos & 3))) & 1;
}

namespace dsu {
    int p[MAXM * 4];
    inline void init(int n) { for (int i = 0; i < n; ++i) p[i] = i; }
    inline int root(int u) { return (p[u] == u) ? u : (p[u] = root(p[u])); }
    inline bool merge(int u, int v) { if ((u = root(u)) != (v = root(v))) { if (rand() & 1) p[u] = v; else p[v] = u; return true; } else return false; }
}

int main()
{
    srand(20171027);
    scanf("%d%d", &n, &m); m /= 4;

    for (int i = 0; i < m; ++i) t[i] = 0;
    dsu::init(m * 4);

    int scc = 0;

    for (int i = 0; i < n; ++i) {
        getchar();
        for (int j = 0; j < m; ++j) s[j] = hex(getchar());
        int left = -1;
        for (int j = 0; j < m * 4; ++j) {
            if (col(s, j)) {
                if (col(t, j)) {
                    if (left != -1 && dsu::merge(j, left)) {
                        --scc;
                    }
                } else {
                    if (left == -1) ++scc;
                }
                dsu::p[j] = (left == -1) ? (col(t, j) ? dsu::p[j] : j) : left;
                left = dsu::p[j];
            } else {
                left = -1;
            }
        }

        memcpy(t, s, sizeof s);
    }

    printf("%d\n", scc);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
static const int MAXN = (1 << 12) + 3;
static const int MAXM = (1 << 12) + 4;

int n, m;
int s[MAXM], t[MAXM];

inline int hex(const char c)
{
    if (c >= '0' && c <= '9') return c - '0'; else return c - 'A' + 10;
}

inline bool col(const int *s, int pos)
{
    return (s[pos >> 2] >> ((3 - pos & 3))) & 1;
}

namespace dsu {
    int p[MAXM * 4];
    inline void init(int n) { for (int i = 0; i < n; ++i) p[i] = i; }
    inline int root(int u) { return (p[u] == u) ? u : (p[u] = root(p[u])); }
    inline bool merge(int u, int v) { if ((u = root(u)) != (v = root(v))) { if (rand() & 1) p[u] = v; else p[v] = u; return true; } else return false; }
}

int main()
{
    srand(20171027);
    scanf("%d%d", &n, &m); m /= 4;

    for (int i = 0; i < m; ++i) t[i] = 0;
    dsu::init(m * 4);

    int scc = 0;

    for (int i = 0; i < n; ++i) {
        getchar();
        for (int j = 0; j < m; ++j) s[j] = hex(getchar());
        int left = -1;
        for (int j = 0; j < m * 4; ++j) {
            if (col(s, j)) {
                if (col(t, j)) {
                    if (left != -1 && dsu::merge(j, left)) {
                        --scc;
                        left = j;
                    } else {
                        if (!col(t, j)) dsu::p[j] = j;
                    }
                } else {
                    if (left == -1) {
                        ++scc;
                        if (!col(t, j)) dsu::p[j] = j;
                    } else {
                        dsu::merge(j, left);
                    }
                }
                left = j;
            } else {
                left = -1;
            }
        }

        memcpy(t, s, sizeof s);
    }

    printf("%d\n", scc);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
static const int MAXN = (1 << 12) + 3;
static const int MAXM = (1 << 12) + 4;

int n, m;
int s[MAXM], t[MAXM];

inline int hex(const char c)
{
    if (c >= '0' && c <= '9') return c - '0'; else return c - 'A' + 10;
}

inline bool col(const int *s, int pos)
{
    return (s[pos >> 2] >> ((3 - pos & 3))) & 1;
}

namespace dsu {
    int p[MAXM * 8];
    inline void init(int n) { for (int i = 0; i < n; ++i) p[i] = i; }
    inline int root(int u) { return (p[u] == u) ? u : (p[u] = root(p[u])); }
    inline bool merge(int u, int v) { if ((u = root(u)) != (v = root(v))) { if (rand() & 1) p[u] = v; else p[v] = u; return true; } else return false; }
}

int rep[MAXM * 8];

int main()
{
    srand(20171028);
    scanf("%d%d", &n, &m); m /= 4;

    for (int i = 0; i < m; ++i) t[i] = 0;
    for (int i = 0; i < m * 8; ++i) dsu::p[i] = -1;

    int scc = 0;

    for (int i = 0; i < n; ++i) {
        getchar();
        for (int j = 0; j < m; ++j) s[j] = hex(getchar());

        for (int j = 0; j < m * 4; ++j) if (col(s, j)) {
            if (col(t, j)) {
                dsu::p[m * 4 + j] = dsu::p[j];
                if (j > 0 && col(s, j - 1) && dsu::merge(m * 4 + j - 1, m * 4 + j))
                    --scc;
            } else {
                if (j > 0 && col(s, j - 1)) {
                    dsu::p[m * 4 + j] = dsu::p[m * 4 + j - 1];
                } else {
                    dsu::p[m * 4 + j] = m * 4 + j;
                    ++scc;
                }
            }
        }

        for (int j = 0; j < m * 8; ++j) if (dsu::p[j] != -1) dsu::root(j);
        for (int j = 0; j < m * 4; ++j) dsu::p[j] = dsu::p[m * 4 + j];
        for (int j = 0; j < m * 8; ++j) rep[j] = -1;
        for (int j = 0; j < m * 4; ++j) {
            if (rep[dsu::p[j]] == -1) rep[dsu::p[j]] = j;
            dsu::p[j] = rep[dsu::p[j]];
        }

        memcpy(t, s, sizeof s);
    }

    printf("%d\n", scc);
    return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
static const int MAXN = (1 << 12) + 3;
static const int MAXM = (1 << 12) + 4;

int n, m;
int s[MAXM], t[MAXM];

inline int hex(const char c)
{
    if (c >= '0' && c <= '9') return c - '0'; else return c - 'A' + 10;
}

inline bool col(const int *s, int pos)
{
    return (s[pos >> 2] >> ((3 - pos & 3))) & 1;
}

namespace dsu {
    int p[MAXM * 4];
    inline void init(int n) { for (int i = 0; i < n; ++i) p[i] = i; }
    inline int root(int u) { return (p[u] == u) ? u : (p[u] = root(p[u])); }
    inline bool merge(int u, int v) { if ((u = root(u)) != (v = root(v))) { if (rand() & 1) p[u] = v; else p[v] = u; return true; } else return false; }
}

int main()
{
    srand(20171027);
    scanf("%d%d", &n, &m); m /= 4;

    for (int i = 0; i < m; ++i) t[i] = 0;
    dsu::init(m * 4);

    int scc = 0;

    for (int i = 0; i < n; ++i) {
        getchar();
        for (int j = 0; j < m; ++j) s[j] = hex(getchar());
        int left = -1;
        for (int j = 0; j < m * 4; ++j) {
            if (col(s, j)) {
                if (col(t, j)) {
                    if (left != -1 && dsu::merge(j, left)) {
                        --scc;
                    } else {
                        if (!col(t, j)) dsu::p[j] = j;
                    }
                } else {
                    if (left == -1) {
                        ++scc;
                        if (!col(t, j)) dsu::p[j] = j;
                    } else {
                        dsu::merge(j, left);
                    }
                }
                left = j;
            } else {
                dsu::p[j] = j;
                left = -1;
            }
        }

        memcpy(t, s, sizeof s);
    }

    printf("%d\n", scc);
    return 0;
}


/*input
2 8
5F
E3
*/
#include <bits/stdc++.h>
using namespace std;
unsigned short par[1<<15];
bool a[1<<14];
int ans,n,m;
int find(int x){return x==par[x]?x:par[x]=find(par[x]);}
void uni(int x, int y){
	if(find(x)==find(y)) return;
	--ans;
	par[find(x)]=find(y);
}
int main(){
	ios_base::sync_with_stdio(0);
	cin.tie(0);
	string s;
	cin>>n>>m;
	for(int i=0;i<n;++i){
		cin>>s;
		for(int i=0;i<m/4;++i){
			int x=(s[i]<='9'?s[i]-'0':s[i]-'A'+10);
			a[i*4+1]=!!(x&8),a[i*4+2]=!!(x&4),a[i*4+3]=!!(x&2),a[i*4+4]=!!(x&1);
		}
		for(int i=1;i<=m;++i)
			if(a[i]) par[i+m]=i+m,++ans;
			else par[i+m]=0;
		for(int i=1;i<=m;++i) if(a[i]){
			if(par[i]) uni(i,i+m);
			if(i&&a[i-1]) uni(i+m-1,i+m);
		}
		for(int i=1;i<=m;++i)
			if(a[i]) par[i]=find(i+m)-m;
			else par[i]=0;
	}
	cout<<ans;
}


#include<bits/stdc++.h>
using namespace std;
const int MXN = (1 << 14) + 10;
int n, m, c, P[2 * MXN];
bool A[MXN];
string s;
int Find(int r)
{
    if (P[r] == r)
        return (r);
    P[r] = Find(P[r]);
    return (P[r]);
}
int Unite(int r, int s)
{
    r = Find(r);
    s = Find(s);
    if (r == s)
        return (0);
    c --;
    P[r] = s;
    return (0);
}
int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    for (int i = 0; i < n; i++)
    {
        cin >> s;
        for (int j = 0; j < m / 4; j++)
        {
            if (s[j] <= '9')
                s[j] -= 48;
            else
                s[j] -= 55;
            A[4 * j + 1] = 8 & s[j];
            A[4 * j + 2] = 4 & s[j];
            A[4 * j + 3] = 2 & s[j];
            A[4 * j + 4] = 1 & s[j];
        }
        for (int j = 1; j <= m; j++)
        {
            if (A[j] == 0)
            {
                P[j + m] = 0;
                continue;
            }
            P[j + m] = j + m;
            c ++;
        }
        for (int j = 1; j <= m; j++)
        {
            if (A[j] == 0)
                continue;
            if (P[j] != 0)
                Unite(j, j + m);
            if (A[j - 1] == 1)
                Unite(j + m - 1, j + m);
        }
        for (int j = 1; j <= m; j++)
        {
            if (A[j] == 1)
                P[j] = Find(j + m) - m;
            else
                P[j] = 0;
        }
    }
    cout << c;
    return (0);
}


#include<bits/stdc++.h>
using namespace std;
const int MXN = (1 << 14) + 10;
int n, m, c, P[2 * MXN];
bool A[MXN];
char b;
int Find(int r)
{
    if (P[r] == r)
        return (r);
    P[r] = Find(P[r]);
    return (P[r]);
}
int Unite(int r, int s)
{
    r = Find(r);
    s = Find(s);
    if (r == s)
        return (0);
    c --;
    P[r] = s;
    return (0);
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m / 4; j++)
        {
            cin >> b;
            if (b <= '9')
                b -= 48;
            else
                b -= 55;
            A[4 * j + 1] = 8 & b;
            A[4 * j + 2] = 4 & b;
            A[4 * j + 3] = 2 & b;
            A[4 * j + 4] = 1 & b;
        }
        for (int j = 1; j <= m; j++)
        {
            if (A[j] == 0)
            {
                P[j + m] = 0;
                continue;
            }
            P[j + m] = j + m;
            c ++;
        }
        for (int j = 1; j <= m; j++)
        {
            if (A[j] == 0)
                continue;
            if (P[j] != 0)
                Unite(j, j + m);
            if (A[j - 1] == 1)
                Unite(j + m - 1, j + m);
        }
        for (int j = 1; j <= m; j++)
        {
            if (A[j] == 1)
                P[j] = Find(j + m) - m;
            else
                P[j] = 0;
        }
    }
    printf("%d", c);
    return (0);
}


#include<bits/stdc++.h>
using namespace std;
const int MXN = (1 << 14) + 10;
int n, m, c, t, P[2 * MXN];
bool A[MXN];
string s;
int Find(int r)
{
    if (P[r] == r)
        return (r);
    P[r] = Find(P[r]);
    return (P[r]);
}
int Unite(int r, int s)
{
    r = Find(r);
    s = Find(s);
    if (r == s)
        return (0);
    c --;
    P[r] = s;
    return (0);
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n; i++)
    {
        cin >> s;
        for (int j = 0; j < m / 4; j++)
        {
            if (s[j] <= '9')
                t = (int)s[j] - 48;
            else
                t = (int)s[j] - 55;
            A[4 * j + 1] = 8 & t;
            A[4 * j + 2] = 4 & t;
            A[4 * j + 3] = 2 & t;
            A[4 * j + 4] = 1 & t;
        }
        for (int j = 1; j <= m; j++)
        {
            if (A[j] == 0)
            {
                P[j + m] = 0;
                continue;
            }
            P[j + m] = j + m;
            c ++;
        }
        for (int j = 1; j <= m; j++)
        {
            if (A[j] == 0)
                continue;
            if (P[j] != 0)
                Unite(j, j + m);
            if (A[j - 1] == 1)
                Unite(j + m - 1, j + m);
        }
        for (int j = 1; j <= m; j++)
        {
            if (A[j] == 1)
                P[j] = Find(j + m) - m;
            else
                P[j] = 0;
        }
    }
    printf("%d", c);
    return (0);
}


#include<bits/stdc++.h>
using namespace std;

int n,m;
int cnt;
int tot;
const int maxn=1<<15;
int fa[2*maxn];
int a[2][maxn];

void readline()
{
	for (int j=0;j<m;j++) a[1][j]=0;
	for (int j=0;j<(m/4);j++)
	{
		char c=getchar();
		int x=c-'0';
		if (c=='A') x=10;
		else if (c=='B') x=11;
		else if (c=='C') x=12;
		else if (c=='D') x=13;
		else if (c=='E') x=14;
		else if (c=='F') x=15;
		for (int i=3;i>=0;i--)
		{
			if (x&1)
			{
				a[1][j*4+i]=1;
				tot++;
			}
			x>>=1;
		}
	}
	getchar();
//	for (int j=0;j<m;j++) if (a[1][j]) putchar('1'); else putchar('0');
//	putchar('\n');
}

int getfa(int x)
{
	if (fa[x]==x) return x;
	else return fa[x]=getfa(fa[x]);
}

void merge(int x,int y)
{
	int f1=getfa(x);
	int f2=getfa(y);
	if (f1!=f2)
	{
		fa[f1]=f2;
		cnt++;
	}
}

int main()
{
	scanf("%d%d",&n,&m);
	getchar();
	for (int i=0;i<m;i++) fa[i]=i;
	for (int i=0;i<n;i++)
	{
		readline();
		for (int j=m;j<m*2;j++) fa[j]=j;
		for (int j=1;j<m;j++) if (a[1][j-1]&&a[1][j]) merge(j-1+m,j+m);
		for (int j=0;j<m;j++) if (a[1][j]&&a[0][j]) merge(j,j+m);
		for (int j=m;j<m*2;j++) fa[j]=getfa(j);
		for (int j=m;j<m*2;j++) if (fa[j]>=m) fa[j-m]=fa[j]-m; else fa[j-m]=fa[j];
		for (int j=0;j<m;j++) a[0][j]=a[1][j];
	}
	printf("%d",tot-cnt);
	return 0;
}


#include<cstdio>
#include<iostream>
#define maxn 32800
using namespace std;
bool b[2][maxn];
int n,m,i,j,k,t,f[2000000],a[maxn],c[2][maxn],d[2000000],x,y,top,ans;
int read()
{
	char c=getchar();
	while(!isdigit(c)&&!isalpha(c))c=getchar();
	if(isdigit(c))return c-'0';else return c-'A'+10;
}
int find(int x)
{
	return x==f[x]?x:f[x]=find(f[x]);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(i=1;i<=m*2;i++)
		d[i]=i;
	top=m*2;
	for(k=1;k<=n+1;k++,t=!t)
	{
		for(i=1;i<=m/4;i++)
		{
			if(k<=n)x=read();else x=0;
			for(j=4;j;j--)
			{
				b[t][(i-1)*4+j]=x&1;
				c[t][(i-1)*4+j]=0;
				x>>=1;
			}
		}
		for(i=1;i<=m;i=j+1)
		{
			j=i;
			if(!b[t][i])continue;
			x=d[top--];
			f[x]=x;
			while(j<=m&&b[t][j])
			{
				c[t][j]=x;
				j++;
			}
		}
		for(i=1;i<=m;i++)
			if(b[t][i]&&b[!t][i])
			{
				x=find(c[t][i]);y=find(c[!t][i]);
				f[y]=x;
				if(x!=y)a[x]+=a[y];
			}
		for(i=1;i<=m;i++)
			if(b[t][i])a[find(c[t][i])]++;
		for(i=1;i<=m;i++)
		{
			if(!b[!t][i])continue;
			x=find(c[!t][i]);
			if(!--a[x])
			{
				d[++top]=x;
				f[x]=0;
				ans++;
			}
		}
	}
	cout<<ans<<endl;
}


#include<cstdio>
#include<iostream>
#define maxn 32800
using namespace std;
bool b[2][maxn];
int n,m,i,j,k,t,f[maxn],a[maxn],c[2][maxn],d[maxn],x,y,top,ans;
int read()
{
	char c=getchar();
	while(!isdigit(c)&&!isalpha(c))c=getchar();
	if(isdigit(c))return c-'0';else return c-'A'+10;
}
int find(int x)
{
	return x==f[x]?x:f[x]=find(f[x]);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(i=1;i<=m*2;i++)
		d[i]=i;
	top=m*2;
	for(k=1;k<=n+1;k++,t=!t)
	{
		for(i=1;i<=m/4;i++)
		{
			if(k<=n)x=read();else x=0;
			for(j=4;j;j--)
			{
				b[t][(i-1)*4+j]=x&1;
				c[t][(i-1)*4+j]=0;
				x>>=1;
			}
		}
		for(i=1;i<=m;i=j+1)
		{
			j=i;
			if(!b[t][i])continue;
			x=d[top--];
			f[x]=x;
			while(j<=m&&b[t][j])
			{
				c[t][j]=x;
				j++;
			}
		}
		for(i=1;i<=m;i++)
			if(b[t][i]&&b[!t][i])
			{
				x=find(c[t][i]);y=find(c[!t][i]);
				f[y]=x;
				if(x!=y)a[x]+=a[y];
			}
		for(i=1;i<=m;i++)
			if(b[t][i])a[find(c[t][i])]++;
		for(i=1;i<=m;i++)
		{
			if(!b[!t][i])continue;
			x=find(c[!t][i]);
			if(!--a[x])
			{
				d[++top]=x;
				f[x]=0;
				ans++;
			}
		}
	}
	cout<<ans<<endl;
}


#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<cstring>
#define maxn 16400
using namespace std;
bool b[2][maxn],bo[maxn];
int n,m,i,j,k,l,t,a[maxn],c[2][maxn],f[maxn],d[maxn],x,y,top,ans,xx,yy;
int read()
{
	char c=getchar();
	while(!isdigit(c)&&!isalpha(c))c=getchar();
	if(isdigit(c))return c-'0';else return c-'A'+10;
}
int find(int x)
{
	return x==f[x]?x:f[x]=find(f[x]);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;++i)
		d[i]=i,f[i]=i;
	top=m;
	for(k=1;k<=n+1;++k,t=!t)
	{
		for(i=1;i<=m/4;++i)
		{
			if(k<=n)x=read();
			else x=0;
			for(j=4;j;j--)
			{
				b[t][(i-1)*4+j]=x&1;
				c[t][(i-1)*4+j]=0;
				x>>=1;
			}
		}
		memset(bo,0,sizeof(bo));
		for(i=1;i<=m;i=j+1)
		{
			j=i;
			if(!b[t][i])continue;
			x=0;
			while(j<=m&&b[t][j])
			{
				if(b[!t][j])
					if(x)
					{
						xx=find(c[!t][j]);
						yy=find(c[!t][x]);
						f[yy]=xx;
						if(xx!=yy)a[xx]+=a[yy];
					}else x=j;
				j++;
			}
			if(x)y=find(c[!t][x]);else y=d[top--];
			for(l=i;l<j;l++)
				c[t][l]=y;
			bo[y]=1;
			a[y]+=j-i;
		}
		for(i=1;i<=m;i++)
			if(b[!t][i])if(!--a[find(c[!t][i])])ans++;
		top=0;
		for(i=1;i<=m;i++)
			if(!bo[i])
			{
				d[++top]=i;
				f[i]=i;
				a[i]=0;
			}
	}
	cout<<ans<<endl;
}


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
#include <stdio.h>
using namespace std;

class Point {
public:
    int row;
    int index;
    Point *parent;
};

Point* get(Point* point) {

    if (point->parent != point) {
        point->parent = get(point->parent);
        return point->parent;
    }

    return point;
}

int merge(Point* left, Point* right) {
    left = get(left);
    right = get(right);

    if (left == right) {
        return 0;
    }

    right->parent = left;
    return 1;
}

int value[1024*16];
int lastValue[1024*16];
char s[1024*16];
Point *root;
Point *lastRoot;

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;

    for (int row=0; row<n; ++row) {
        scanf("%s", s);
        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            value[index*4+0] = (c&8)>0?1:0;
            value[index*4+1] = (c&4)>0?1:0;
            value[index*4+2] = (c&2)>0?1:0;
            value[index*4+3] = (c&1)>0?1:0;
        }

        root = new Point[1024*16];
        for (int index=0; index<m; ++index) {

            root[index].parent = &root[index];

            if (value[index] == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && value[index-1] == 1) {
                sum -= merge(&root[index-1], &root[index]);
            }

            if (row > 0 && lastValue[index] == 1) {
                sum -= merge(&root[index], &lastRoot[index]);
            }
        }

        for (int index=0; index<m; ++index) {
            lastValue[index] = value[index];
        }
        delete []lastRoot;
        lastRoot = root;
    }

    cout<<sum<<endl;

    return 0;
}

/*
 2 4
 8
 8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
#include <stdio.h>
using namespace std;

class Point {
public:
    int value;
    Point *parent;

public:
    Point* getRoot();
};

Point* Point::getRoot() {
    if (this->parent != this) {
        this->parent = this->getRoot();
        return this->parent;
    }
	return this;
}

int merge(Point* left, Point* right) {
    left = left->getRoot();
    right = right->getRoot();

    if (left == right) {
        return 0;
    }

    right->parent = left;
    return 1;
}

char s[1024*16];
Point *root;
Point *lastRoot;

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;

    for (int row=0; row<n; ++row) {
        scanf("%s", s);
        root = new Point[1024*16];

        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            root[index*4+0].value = (c&8)>0?1:0;
            root[index*4+1].value = (c&4)>0?1:0;
            root[index*4+2].value = (c&2)>0?1:0;
            root[index*4+3].value = (c&1)>0?1:0;
        }

        for (int index=0; index<m; ++index) {

            root[index].parent = &root[index];

            if (root[index].value == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && root[index-1].value == 1) {
                sum -= merge(&root[index-1], &root[index]);
            }

            if (row > 0 && lastRoot[index].value == 1) {
                sum -= merge(&root[index], &lastRoot[index]);
            }
        }

        delete []lastRoot;
        lastRoot = root;
    }

    cout<<sum<<endl;

    return 0;
}

/*
 2 4
 8
 8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
#include <stdio.h>
using namespace std;

class Point {
public:
    int value;
    Point *parent;

public:
    Point* getRoot();
    int merge(Point* point);
};

Point* Point::getRoot() {
    if (this->parent != this) {
        this->parent = this->getRoot();
        return this->parent;
    }
	return this;
}

int Point::merge(Point* point) {
    this->getRoot();
    point = point->getRoot();

    if (this->parent == point) {
        return 0;
    }

    point->parent = this->parent;
    return 1;
}

char s[1024*16];
Point *root;
Point *lastRoot;

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;

    for (int row=0; row<n; ++row) {
        scanf("%s", s);
        root = new Point[1024*16];

        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            root[index*4+0].value = (c&8)>0?1:0;
            root[index*4+1].value = (c&4)>0?1:0;
            root[index*4+2].value = (c&2)>0?1:0;
            root[index*4+3].value = (c&1)>0?1:0;
        }

        for (int index=0; index<m; ++index) {

            root[index].parent = &root[index];

            if (root[index].value == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && root[index-1].value == 1) {
                sum -= root[index-1].merge(&root[index]);
            }

            if (row > 0 && lastRoot[index].value == 1) {
                sum -= root[index].merge(&lastRoot[index]);
            }
        }

        delete []lastRoot;
        lastRoot = root;
    }

    cout<<sum<<endl;

    return 0;
}

/*
 2 4
 8
 8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
using namespace std;

//class Point {
//public:
//    Point *parent;
//};
//
//Point* get(Point* point) {
//
//    if (point->parent != point) {
//        point->parent = get(point->parent);
//        return point->parent;
//    }
//
//    return point;
//}
//
//int merge(Point* left, Point* right) {
//    left = get(left);
//    right = get(right);
//
//    if (left == right) {
//        return 0;
//    }
//
//    right->parent = left;
//    return 1;
//}

int value[1024*16];
int lastValue[1024*16];
int root[1024*16*2];

int get(int i) {
    if (root[i] != i) {
        root[i] = get(root[i]);
        return root[i];
    }
    return i;
}

int merge(int left, int right) {
    left = get(left);
    right = get(right);

    if (left == right) {
        return 0;
    }

    root[right] = left;
    return 1;
}

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;
    string s;

    for (int i=0; i<m*2; ++i) {
        root[i] = i;
    }

    for (int row=0; row<n; ++row) {
        cin>>s;
        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            value[index*4+0] = (c&8)>0?1:0;
            value[index*4+1] = (c&4)>0?1:0;
            value[index*4+2] = (c&2)>0?1:0;
            value[index*4+3] = (c&1)>0?1:0;
        }

        for (int index=0; index<m; ++index) {

            if (value[index] == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && value[index - 1] == 1) {
                sum -= merge(m + index - 1, m + index);
            }

            if (row > 0 && lastValue[index] == 1) {
                sum -= merge(m + index, index);
            }
        }

        for (int index=0; index<m; ++index) {
            lastValue[index] = value[index];
            root[index] = root[m + index] - m;
            root[m + index] = m + index;
            //cout<<root[index]<<" ";
        }

        //cout<<endl;

    }

    cout<<sum<<endl;

    return 0;
}

/*
2 4
8
8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
#include <time.h>
using namespace std;

//class Point {
//public:
//    Point *parent;
//};
//
//Point* get(Point* point) {
//
//    if (point->parent != point) {
//        point->parent = get(point->parent);
//        return point->parent;
//    }
//
//    return point;
//}
//
//int merge(Point* left, Point* right) {
//    left = get(left);
//    right = get(right);
//
//    if (left == right) {
//        return 0;
//    }
//
//    right->parent = left;
//    return 1;
//}

int value[1024*16];
int lastValue[1024*16];
int root[1024*16*2];
char s[1024*16];

int get(int i) {
    if (root[i] != i) {
        root[i] = get(root[i]);
        return root[i];
    }
    return i;
}

int merge(int left, int right) {
    left = get(left);
    right = get(right);

    if (left == right) {
        return 0;
    }

    root[right] = left;
    return 1;
}

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;

    clock_t  t;
    t = clock();

    for (int i=0; i<m*2; ++i) {
        root[i] = i;
    }

    for (int row=0; row<n; ++row) {
        //cin>>s;
        scanf("%s", s);

//        for (int i=0; i<16384; ++i) {
//            s[i]= 'F';
//        }

        //cout<<"1:"<<clock() - t<<endl;

        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            value[index*4+0] = (c&8)>0?1:0;
            value[index*4+1] = (c&4)>0?1:0;
            value[index*4+2] = (c&2)>0?1:0;
            value[index*4+3] = (c&1)>0?1:0;
        }

        //cout<<"2:"<<clock() - t<<endl;

        for (int index=0; index<m; ++index) {

            if (value[index] == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && value[index - 1] == 1) {
                sum -= merge(m + index - 1, m + index);
            }

            if (row > 0 && lastValue[index] == 1) {
                sum -= merge(m + index, index);
            }
        }

        //cout<<"3:"<<clock() - t<<endl;

        for (int index=0; index<m; ++index) {
            lastValue[index] = value[index];
            root[index] = root[m + index] - m;
            root[m + index] = m + index;
            //cout<<root[index]<<" ";
        }

        //cout<<endl;

    }

    cout<<sum<<endl;
    //cout<<clock() - t<<endl;

    return 0;
}

/*
2 4
8
8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
using namespace std;

//class Point {
//public:
//    Point *parent;
//};
//
//Point* get(Point* point) {
//
//    if (point->parent != point) {
//        point->parent = get(point->parent);
//        return point->parent;
//    }
//
//    return point;
//}
//
//int merge(Point* left, Point* right) {
//    left = get(left);
//    right = get(right);
//
//    if (left == right) {
//        return 0;
//    }
//
//    right->parent = left;
//    return 1;
//}

int value[1024*16];
int lastValue[1024*16];
int root[1024*16*2];

int get(int i) {
    if (root[i] != i) {
        root[i] = get(root[i]);
        return root[i];
    }
    return i;
}

int merge(int left, int right) {
    left = get(left);
    right = get(right);

    if (left == right) {
        return 0;
    }

    root[right] = left;
    return 1;
}

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;
    string s;

    for (int i=0; i<m*2; ++i) {
        root[i] = i;
    }

    for (int row=0; row<n; ++row) {
        cin>>s;
        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            value[index*4+0] = (c&8)>0?1:0;
            value[index*4+1] = (c&4)>0?1:0;
            value[index*4+2] = (c&2)>0?1:0;
            value[index*4+3] = (c&1)>0?1:0;
        }

        for (int index=0; index<m; ++index) {

            if (value[index] == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && value[index - 1] == 1) {
                sum -= merge(m + index, m + index - 1);
            }

            if (row > 0 && lastValue[index] == 1) {
                sum -= merge(m + index, index);
            }
        }

        for (int index=0; index<m; ++index) {
            lastValue[index] = value[index];
            root[index] = root[m + index] - m;
            root[m + index] = m + index;
            //cout<<root[index]<<" ";
        }

        //cout<<endl;

    }

    cout<<sum<<endl;

    return 0;
}

/*
2 4
8
8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
using namespace std;

class Point {
public:
    int row;
    int index;
    Point *parent;
};

Point* get(Point* point) {

    if (point->parent != point) {
        point->parent = get(point->parent);
        return point->parent;
    }

    return point;
}

int merge(Point* left, Point* right) {
    left = get(left);
    right = get(right);

    if (left == right) {
        return 0;
    }

    right->parent = left;
    return 1;
}

int value[1024*16];
int lastValue[1024*16];
Point *root;
Point *lastRoot;

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;
    string s;
    for (int row=0; row<n; ++row) {
        cin>>s;
        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            value[index*4+0] = (c&8)>0?1:0;
            value[index*4+1] = (c&4)>0?1:0;
            value[index*4+2] = (c&2)>0?1:0;
            value[index*4+3] = (c&1)>0?1:0;
        }

        root = new Point[1024*16];
        for (int index=0; index<m; ++index) {

            root[index].parent = &root[index];

            if (value[index] == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && value[index-1] == 1) {
                sum -= merge(&root[index-1], &root[index]);
            }

            if (row > 0 && lastValue[index] == 1) {
                sum -= merge(&root[index], &lastRoot[index]);
            }
        }

        for (int index=0; index<m; ++index) {
            lastValue[index] = value[index];
        }
        delete []lastRoot;
        lastRoot = root;
    }

    cout<<sum<<endl;

    return 0;
}

/*
 2 4
 8
 8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
using namespace std;

class Point {
public:
    int row;
    int index;
    Point *parent;
};

Point* get(Point* point) {

    if (point->parent != point) {
        point->parent = get(point->parent);
        return point->parent;
    }

    return point;
}

int merge(Point* left, Point* right) {
    left = get(left);
    right = get(right);

    if (left == right) {
        return 0;
    }

    right->parent = left;
    return 1;
}

int value[1024*16];
int lastValue[1024*16];
char s[1024*16];
Point *root;
Point *lastRoot;

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;

    for (int row=0; row<n; ++row) {
        scanf("%s", s);
        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            value[index*4+0] = (c&8)>0?1:0;
            value[index*4+1] = (c&4)>0?1:0;
            value[index*4+2] = (c&2)>0?1:0;
            value[index*4+3] = (c&1)>0?1:0;
        }

        root = new Point[1024*16];
        for (int index=0; index<m; ++index) {

            root[index].parent = &root[index];

            if (value[index] == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && value[index-1] == 1) {
                sum -= merge(&root[index-1], &root[index]);
            }

            if (row > 0 && lastValue[index] == 1) {
                sum -= merge(&root[index], &lastRoot[index]);
            }
        }

        for (int index=0; index<m; ++index) {
            lastValue[index] = value[index];
        }
        delete []lastRoot;
        lastRoot = root;
    }

    cout<<sum<<endl;

    return 0;
}

/*
 2 4
 8
 8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
using namespace std;

class Point {
public:
    int row;
    int index;
    Point *parent;
};

Point* get(Point* point) {

    if (point->parent != point) {
        point->parent = get(point->parent);
        return point->parent;
    }

    return point;
}

int merge(Point* left, Point* right) {
    left = get(left);
    right = get(right);

    if (left == right) {
        return 0;
    }

    right->parent = left;
    return 1;
}

int value[1024*16];
int lastValue[1024*16];
Point root[1024*16];
Point lastRoot[1024*16];

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;
    string s;
    for (int row=0; row<n; ++row) {
        cin>>s;
        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            value[index*4+0] = (c&8)>0?1:0;
            value[index*4+1] = (c&4)>0?1:0;
            value[index*4+2] = (c&2)>0?1:0;
            value[index*4+3] = (c&1)>0?1:0;
        }

        for (int index=0; index<m; ++index) {

            Point* point = new Point();
            point->row = row;
            point->index = index;
            point->parent = point;
            root[index] = *point;

            if (value[index] == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && value[index-1] == 1) {
                sum -= merge(&root[index-1], &root[index]);
            }

            if (row > 0 && lastValue[index] == 1) {
                sum -= merge(&root[index], &lastRoot[index]);
            }
        }

        for (int index=0; index<m; ++index) {
            lastValue[index] = value[index];
            lastRoot[index] = root[index];
            // cout<<lastRoot[index].parent->index<<" ";
        }
        // cout<<endl;

    }

    cout<<sum<<endl;

    return 0;
}

/*
2 4
8
8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
#include <stdio.h>
using namespace std;

class Point {
public:
    int value;
    Point *parent;
};

Point* get(Point* point) {

    if (point->parent != point) {
        point->parent = get(point->parent);
        return point->parent;
    }

    return point;
}

int merge(Point* left, Point* right) {
    left = get(left);
    right = get(right);

    if (left == right) {
        return 0;
    }

    right->parent = left;
    return 1;
}

char s[1024*16];
Point *root;
Point *lastRoot;

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;

    for (int row=0; row<n; ++row) {
        scanf("%s", s);
        root = new Point[1024*16];

        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            root[index*4+0].value = (c&8)>0?1:0;
            root[index*4+1].value = (c&4)>0?1:0;
            root[index*4+2].value = (c&2)>0?1:0;
            root[index*4+3].value = (c&1)>0?1:0;
        }

        for (int index=0; index<m; ++index) {

            root[index].parent = &root[index];

            if (root[index].value == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && root[index-1].value == 1) {
                sum -= merge(&root[index-1], &root[index]);
            }

            if (row > 0 && lastRoot[index].value == 1) {
                sum -= merge(&root[index], &lastRoot[index]);
            }
        }

        delete []lastRoot;
        lastRoot = root;
    }

    cout<<sum<<endl;

    return 0;
}

/*
 2 4
 8
 8
 */


//
//  main.cpp
//  ACM
//
//  Created by Tconan on 2017/11/8.
//  Copyright © 2017年 Tconan. All rights reserved.
//

#include <iostream>
#include <stdio.h>
#include <time.h>
using namespace std;

//class Point {
//public:
//    Point *parent;
//};
//
//Point* get(Point* point) {
//
//    if (point->parent != point) {
//        point->parent = get(point->parent);
//        return point->parent;
//    }
//
//    return point;
//}
//
//int merge(Point* left, Point* right) {
//    left = get(left);
//    right = get(right);
//
//    if (left == right) {
//        return 0;
//    }
//
//    right->parent = left;
//    return 1;
//}

int value[1024*16];
int lastValue[1024*16];
int root[1024*16*2];
char s[1024*16];

int get(int i) {
    if (root[i] != i) {
        root[i] = get(root[i]);
        return root[i];
    }
    return i;
}

int merge(int left, int right) {
    left = get(left);
    right = get(right);

    if (left == right) {
        return 0;
    }

    root[right] = left;
    return 1;
}

int main(int argc, const char * argv[]) {

    int n, m, sum = 0;
    cin>>n>>m;

    clock_t  t;
    t = clock();

    for (int i=0; i<m*2; ++i) {
        root[i] = i;
    }

    for (int row=0; row<n; ++row) {
        //cin>>s;
        scanf("%s", s);

//        for (int i=0; i<16384; ++i) {
//            s[i]= 'F';
//        }

        //cout<<"1:"<<clock() - t<<endl;

        for (int index=0; index<m/4; ++index) {
            char c = s[index];
            if (c >= 'A') {
                c = c - 'A' + '9' + 1;
            }

            value[index*4+0] = (c&8)>0?1:0;
            value[index*4+1] = (c&4)>0?1:0;
            value[index*4+2] = (c&2)>0?1:0;
            value[index*4+3] = (c&1)>0?1:0;
        }

        //cout<<"2:"<<clock() - t<<endl;

        for (int index=0; index<m; ++index) {

            if (value[index] == 0) {
                continue;
            }
            sum ++;

            if (index > 0 && value[index - 1] == 1) {
                sum -= merge(m + index - 1, m + index);
            }

            if (row > 0 && lastValue[index] == 1) {
                sum -= merge(m + index, index);
            }
        }

        //cout<<"3:"<<clock() - t<<endl;

        for (int index=0; index<m; ++index) {
            lastValue[index] = value[index];
            root[index] = root[m + index] - m;
            root[m + index] = m + index;
            //cout<<root[index]<<" ";
        }

        //cout<<endl;

    }

    cout<<sum<<endl;
    //cout<<clock() - t<<endl;

    return 0;
}

/*
2 4
8
8
 */


#include<bits/stdc++.h>

using namespace std;

const int maxn = 1 << 15;

int n, m, a;

long long ans;

int f[maxn], p[maxn];

int now[maxn], last[maxn];

int vis[maxn];

int find( int u ) {

  if( f[u] == u ) return u;

  else return f[u] = find( f[u] );

}

int main() {

  cin >> n >> m;

  for( int i = 0; i < m; i ++ ) vis[i] = -1, f[i] = i;

  while( n -- ) {

    memset( now, 0, sizeof( now ));

    for( int i = 0, j; i < m >> 2; i ++ ) {

      scanf("%1x", &a );

      j = 3;

      while( j >= 0 ) {

        now[i * 4 + j] = a % 2;

        a /= 2;

        j--;

      }

    }

    for( int i = 0; i < m; i ++ ) {

      if( last[i] & now[i] ) {

        if( vis[p[i]] != -1 ) f[i] = vis[p[i]];

        else vis[p[i]] = i;

      } else if( now[i] ) ans++;

      last[i] = now[i];

    }

    for( int i = 0, fx, fy; i < m - 1; i ++ ) if( now[i] and now[i + 1] ) {

      fx = find( i ); fy = find( i + 1 );

      if( fx != fy ) {

        f[fy] = fx; ans--;

      }

    }

    for( int i = 0; i < m; i ++ ) {

      p[i] = find(i);

      f[i] = i; vis[i] = -1;

    }

  }

  cout << ans << endl;

  return 0;

}


#include<bits/stdc++.h>

using namespace std;

const int maxn = 1 << 15;

int n, m, a, fx, fy;

long long ans;

int f[maxn], p[maxn];

int now[maxn], last[maxn];

int vis[maxn];

int find( int u ) {

  if( f[u] == u ) return u;

  else return f[u] = find( f[u] );

}

int main() {

  scanf("%d%d", &n, &m);

  while( n -- ) {

    for( int i = 0, j; i < m >> 2; i ++ ) {

      scanf("%1x", &a );

      j = 3;

      while( j >= 0 ) {

        now[i * 4 + j] = a % 2;

        a /= 2;

        j--;

      }

    }

    for( int i = 0; i < m; i ++ ) vis[i] = -1, f[i] = i;

    for( int i = 0; i < m; i ++ ) {

      if( last[i] & now[i] ) {

        if( vis[p[i]] != -1 ) f[i] = vis[p[i]];

        else vis[p[i]] = i;

      } else if( now[i] ) ans++;

      last[i] = now[i];

    }

    for( int i = 0; i < m - 1; i ++ ) if( now[i] and now[i + 1] ) {

      fx = find( i ); fy = find( i + 1 );

      if( fx != fy ) {

        f[fy] = fx; ans--;

      }

    }

    for( int i = 0; i < m; i ++ ) p[i] = find(i);

  }

  cout << ans << endl;

  return 0;

}


#include<bits/stdc++.h>

using namespace std;

const int maxn = 1 << 15;

int n, m, a;

long long ans;

int f[maxn], p[maxn];

int now[maxn], last[maxn];

int vis[maxn];

int find( int u ) {

  if( f[u] == u ) return u;

  else return f[u] = find( f[u] );

}

int main() {

  cin >> n >> m;

  while( n -- ) {

    memset( now, 0, sizeof( now ));

    for( int i = 0, j; i < m >> 2; i ++ ) {

      scanf("%1x", &a );

      j = 3;

      while( a ) {

        now[i * 4 + j] = a % 2;

        a /= 2;

        j--;

      }

    }

    for( int i = 0; i < m; i ++ ) f[i] = i, vis[i] = 0;

    for( int i = 0; i < m; i ++ ) {

      if( last[i] & now[i] ) {

        if( vis[p[i]] ) f[i] = vis[p[i]];

        else vis[p[i]] = i;

      } else if( now[i] ) ans++;

    }

    for( int i = 0, fx, fy; i < m - 1; i ++ ) if( now[i] and now[i + 1] ) {

      fx = find( i ); fy = find( i + 1 );

      if( fx != fy ) {

        f[fy] = fx; ans--;

      }

    }

    for( int i = 0; i < m; i ++ ) f[i] = find(i);

    for( int i = 0; i < m; i ++ ) p[i] = f[i];

    for( int i = 0; i < m; i ++ ) last[i] = now[i], now[i] = 0;

  }

  cout << ans << endl;

  return 0;

}


#include<bits/stdc++.h>

using namespace std;

const int maxn = 1 << 15;

int n, m, a;

long long ans;

int f[maxn], p[maxn];

int now[maxn], last[maxn];

int vis[maxn];

int find( int u ) {

  if( f[u] == u ) return u;

  else return f[u] = find( f[u] );

}

int main() {

  cin >> n >> m;

  while( n -- ) {

    memset( now, 0, sizeof( now ));

    for( int i = 0, j; i < m >> 2; i ++ ) {

      scanf("%1x", &a );

      j = 3;

      while( j >= 0 ) {

        now[i * 4 + j] = a % 2;

        a /= 2;

        j--;

      }

    }

    for( int i = 0; i < m; i ++ ) vis[i] = -1, f[i] = i;

    for( int i = 0; i < m; i ++ ) {

      if( last[i] & now[i] ) {

        if( vis[p[i]] != -1 ) f[i] = vis[p[i]];

        else vis[p[i]] = i;

      } else if( now[i] ) ans++;

      last[i] = now[i];

    }

    for( int i = 0, fx, fy; i < m - 1; i ++ ) if( now[i] and now[i + 1] ) {

      fx = find( i ); fy = find( i + 1 );

      if( fx != fy ) {

        f[fy] = fx; ans--;

      }

    }

    for( int i = 0; i < m; i ++ ) p[i] = find(i);

  }

  cout << ans << endl;

  return 0;

}


#include<bits/stdc++.h>

using namespace std;

const int maxn = 1 << 15;

int n, m, a;

long long ans;

int f[maxn], p[maxn];

int now[maxn], last[maxn];

int vis[maxn];

int find( int u ) {

  if( f[u] == u ) return u;

  else return f[u] = find( f[u] );

}

int main() {

  cin >> n >> m;

  while( n -- ) {

    memset( now, 0, sizeof( now ));

    for( int i = 0, j; i < m >> 2; i ++ ) {

      scanf("%1x", &a );

      j = 3;

      while( j >= 0 ) {

        now[i * 4 + j] = a % 2;

        a /= 2;

        j--;

      }

    }

    for( int i = 0; i < m; i ++ ) f[i] = i, vis[i] = -1;

    for( int i = 0; i < m; i ++ ) {

      if( last[i] & now[i] ) {

        if( vis[p[i]] != -1 ) f[i] = vis[p[i]];

        else vis[p[i]] = i;

      } else if( now[i] ) ans++;

    }

    for( int i = 0, fx, fy; i < m - 1; i ++ ) if( now[i] and now[i + 1] ) {

      fx = find( i ); fy = find( i + 1 );

      if( fx != fy ) {

        f[fy] = fx; ans--;

      }

    }

    for( int i = 0; i < m; i ++ ) f[i] = find(i);

    for( int i = 0; i < m; i ++ ) p[i] = f[i];

    for( int i = 0; i < m; i ++ ) last[i] = now[i];

  }

  cout << ans << endl;

  return 0;

}


#include<bits/stdc++.h>

using namespace std;

const int maxn = 1 << 15;

int n, m, a, fx, fy;

long long ans;

int f[maxn], p[maxn];

int now[maxn], last[maxn];

int vis[maxn];

int find( int u ) {

  if( f[u] == u ) return u;

  else return f[u] = find( f[u] );

}

int get_int( char c ) {

  if( '0' <= c and c <= '9' ) return c - '0';

  return c - 'A' + 10;

}

char buf[maxn];

int main() {

  scanf("%d%d", &n, &m);

  while( n -- ) {

    scanf(" ");

    gets(buf);

    for( int i = 0, j; i < m >> 2; i ++ ) {

      a = get_int( buf[i] );

      j = 3;

      while( j >= 0 ) {

        now[i * 4 + j] = a % 2;

        a /= 2;

        j--;

      }

    }

    for( int i = 0; i < m; i ++ ) vis[i] = -1, f[i] = i;

    for( int i = 0; i < m; i ++ ) {

      if( last[i] & now[i] ) {

        if( vis[p[i]] != -1 ) f[i] = vis[p[i]];

        else vis[p[i]] = i;

      } else if( now[i] ) ans++;

      last[i] = now[i];

    }

    for( int i = 0; i < m - 1; i ++ ) if( now[i] and now[i + 1] ) {

      fx = find( i ); fy = find( i + 1 );

      if( fx != fy ) {

        f[fy] = fx; ans--;

      }

    }

    for( int i = 0; i < m; i ++ ) p[i] = find(i);

  }

  cout << ans << endl;

  return 0;

}


#include<bits/stdc++.h>

using namespace std;

const int maxn = 1 << 15;

int n, m, a;

long long ans;

int f[maxn], p[maxn];

int now[maxn], last[maxn];

int find( int u ) {

  if( f[u] == u ) return u;

  else return f[u] = find( f[u] );

}

int main() {

  cin >> n >> m;

  while( n -- ) {

    memset( now, 0, sizeof( now ));

    for( int i = 0, j; i < m >> 2; i ++ ) {

      scanf("%x", &a );

      j = 3;

      while( a ) {

        now[i * 4 + j] = a % 2;

        a /= 2;

        j--;

      }

    }

    for( int i = 0; i < m; i ++ ) f[i] = i;

    for( int i = 0; i < m; i ++ ) {

      if( last[i] & now[i] ) {

        f[i] = p[i];

      } else if( now[i] ) ans++;

    }

    for( int i = 0, fx, fy; i < m - 1; i ++ ) if( now[i] and now[i + 1] ) {

      fx = find( i ); fy = find( i + 1 );

      if( fx != fy ) {

        f[fy] = fx; ans--;

      }

    }

    for( int i = 0; i < m; i ++ ) p[i] = find( i );

    for( int i = 0; i < m; i ++ ) last[i] = now[i];

  }

  cout << ans << endl;

  return 0;

}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define MAXN 55
typedef __int64 lint;
char a[MAXN][MAXN];
char b[MAXN][MAXN];

int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=0; i<n; i++)
        {
            cin>>a[i];
        }

        int l,r;
        scanf("%d %d",&l,&r);
        for(int i=0; i<l; i++)
            cin>>b[i];

        int cnt=0;
        int maxl=-1000000;
        int X,Y;
        for(int x=-50; x<=50; x++)
            for(int y=-50; y<=50; y++)
            {
                cnt=0;
                for(int i=0; i<=n; i++)
                    for(int j=0; j<=m; j++)
                        if(i+x<=50 && i+x>=0 && j+y<=50 && j+y>=0)
                            if(a[i][j]=='1' && b[i+x][j+y]=='1')   cnt++;

                if(cnt>maxl)
                {

                    maxl=cnt;
                    X=x;
                    Y=y;
                }

            }
        cout<<X<<" "<<Y<<endl;
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define MAXN 55
typedef __int64 lint;
char a[MAXN][MAXN];
char b[MAXN][MAXN];
int A[MAXN][MAXN];
int B[MAXN][MAXN];
int w,s;
int fun(int i,int j,int k,int h)
{
    int cnt=0;
    for(int o=0;o<w;o++)
    {
        for(int p=0;p<s;p++)
        {
            if(A[i+o][j+p]==1&&B[k+o][h+p]==1)
            {

                cnt++;
            }
        }
    }
    return cnt;
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                A[i][j]=a[i][j]-'0';
            }
        }
        int l,r;
        scanf("%d %d",&l,&r);
        for(int i=0;i<l;i++)
            cin>>b[i];
        for(int i=0;i<l;i++)
        {
            for(int j=0;j<r;j++)
            {
                B[i][j]=b[i][j]-'0';

            }

        }

        w=min(n,l);
        s=min(r,m);

        int maxl=-1000000;
        int u,v,t,p;
        for(int i=0;i<=n-w;i++)
        {
            for(int j=0;j<=m-s;j++)
            {
                for(int k=0;k<=l-w;k++)
                {
                    for(int h=0;h<=r-s;h++)
                    {

                        if(fun(i,j,k,h)>maxl)
                        {

                            maxl=fun(i,j,k,h);
                            t=i;
                            p=j;
                            u=k;
                            v=h;
                        }
                    }
                }

            }
        }
        //cout<<maxl<<endl;
        //cout<<u<<" "<<v<<endl;
        //cout<<t<<" "<<p<<endl;
        cout<<u-t<<" "<<v-p<<endl;

    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define MAXN 100
typedef __int64 lint;
char a[MAXN][MAXN];
char b[MAXN][MAXN];
int A[MAXN][MAXN];
int B[MAXN][MAXN];
int w,s;
int fun(int i,int j,int k,int h)
{
    int cnt=0;
    for(int o=0;o<w;o++)
    {
        for(int p=0;p<s;p++)
        {
            if(A[i+o][j+p]==B[k+o][h+p]==1)
            {

                cnt++;
            }
        }
    }
    return cnt;
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                A[i][j]=a[i][j]-'0';
            }
        }
        int l,r;
        scanf("%d %d",&l,&r);
        for(int i=0;i<l;i++)
            cin>>b[i];
        for(int i=0;i<l;i++)
        {
            for(int j=0;j<r;j++)
            {
                B[i][j]=b[i][j]-'0';

            }

        }

        w=min(n,l);
        s=min(r,m);

        int maxl=-1000000;
        int u,v,t,p;
        for(int i=0;i<=n-w;i++)
        {
            for(int j=0;j<=m-s;j++)
            {
                for(int k=0;k<=l-w;k++)
                {
                    for(int h=0;h<=r-s;h++)
                    {

                        if(fun(i,j,k,h)>=maxl)
                        {

                            maxl=fun(i,j,k,h);
                            t=i;
                            p=j;
                            u=k;
                            v=h;
                        }
                    }
                }

            }
        }

        cout<<u-t<<" "<<v-p<<endl;

    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define MAXN 55
typedef __int64 lint;
char a[MAXN][MAXN];
char b[MAXN][MAXN];
int A[MAXN][MAXN];
int B[MAXN][MAXN];
int w,s;
int fun(int i,int j,int k,int h)
{
    int cnt=0;
    for(int o=0;o<w;o++)
    {
        for(int p=0;p<s;p++)
        {
            if(a[i+o][j+p]=='1'&&b[k+o][h+p]=='1')
            {
                cnt++;
            }
        }
    }
    return cnt;
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }

        int l,r;
        scanf("%d %d",&l,&r);
        for(int i=0;i<l;i++)
            cin>>b[i];

        w=min(n,l);
        s=min(r,m);

        int maxl=-1000000;
        int u,v,t,p;
        for(int i=0;i<=n-w;i++)
        {
            for(int j=0;j<=m-s;j++)
            {
                for(int k=0;k<=l-w;k++)
                {
                    for(int h=0;h<=r-s;h++)
                    {

                        if(fun(i,j,k,h)>=maxl)
                        {

                            maxl=fun(i,j,k,h);
                            t=i;
                            p=j;
                            u=k;
                            v=h;
                        }
                    }
                }

            }
        }
        //cout<<maxl<<endl;
        //cout<<u<<" "<<v<<endl;
        //cout<<t<<" "<<p<<endl;
        cout<<u-t<<" "<<v-p<<endl;

    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
#define MAXN 55
typedef __int64 lint;
char a[MAXN][MAXN];
char b[MAXN][MAXN];
int A[MAXN][MAXN];
int B[MAXN][MAXN];
int w,s;
int fun(int i,int j,int k,int h)
{
    int cnt=0;
    for(int o=0;o<w;o++)
    {
        for(int p=0;p<s;p++)
        {
            if(A[i+o][j+p]==B[k+o][h+p]==1)
            {

                cnt++;
            }
        }
    }
    return cnt;
}
int main()
{
    int n,m;
    while(~scanf("%d %d",&n,&m))
    {
        for(int i=0;i<n;i++)
        {
            cin>>a[i];
        }
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                A[i][j]=a[i][j]-'0';
            }
        }
        int l,r;
        scanf("%d %d",&l,&r);
        for(int i=0;i<l;i++)
            cin>>b[i];
        for(int i=0;i<l;i++)
        {
            for(int j=0;j<r;j++)
            {
                B[i][j]=b[i][j]-'0';

            }

        }

        w=min(n,l);
        s=min(r,m);

        int maxl=-1000000;
        int u,v,t,p;
        for(int i=0;i<=n-w;i++)
        {
            for(int j=0;j<=m-s;j++)
            {
                for(int k=0;k<=l-w;k++)
                {
                    for(int h=0;h<=r-s;h++)
                    {

                        if(fun(i,j,k,h)>maxl)
                        {

                            maxl=fun(i,j,k,h);
                            t=i;
                            p=j;
                            u=k;
                            v=h;
                        }
                    }
                }

            }
        }

        cout<<u-t<<" "<<v-p<<endl;

    }
    return 0;
}


#include<iostream>
#include<utility>
#include<algorithm>
#include<cstdio>
#include<string.h>
using namespace std;
int main()
{
    int na,nb,ma,mb,k=0,pi,pj,x,y,sum,tt,uu,max;char c;
    char *s=new char[100];int a[100][100],b[100][100];
    cin>>na>>nb;
    for(int i=0;i<na;i++)
    {
        scanf("%s",s);k=1;
        for(int j=0;j<strlen(s);j++)
        {
            a[i+1][k++]=s[j]-'0';//cout<<a[j+1][k-1]<<" ";
        }
    }

    cin>>ma>>mb;
    for(int i=0;i<ma;i++)
    {
        scanf("%s",s);k=1;
        for(int j=0;j<strlen(s);j++)
        {
            b[i+1][k++]=(s[j]-'0');//cout<<b[j+1][k-1]<<" ";
        }
    }
    /*for(int i=1;i<=na;i++)
    {
        for(int j=1;j<=nb;j++)
        cout<<a[i][j]<<" ";
        cout<<endl;
    }*/
    max=-5;
    for(int i=-ma;i<=ma;i++)
    {
        for(int j=-mb;j<=mb;j++)
        {
            x=i;y=j;sum=0;//cout<<x<<" "<<y<<endl;
            for(int t=1;t<=na;t++)
            {
                for(int u=1;u<=nb;u++)
                {
                    tt=t+x;uu=u+y;
                    /*if(x==0&&y==1)
                    {
                        cout<<tt<<" "<<uu<<"\t";
                    }*/
                    if((tt>=1&&tt<=ma)&&(uu>=1&&uu<=mb))
                    {
                        sum+=(a[t][u]*b[tt][uu]);
                    }
                }
            }
            if(sum>max){max=sum;//cout<<sum<<" sum"<<endl;
            pi=x;pj=y;}
        }
    }
    cout<<pi<<" "<<pj;
}


#include<iostream>
#include<utility>
#include<algorithm>
#include<cstdio>
#include<string>
using namespace std;
int main()
{
    int na,nb,ma,mb,k=0,pi,pj,x,y,sum,tt,uu,max;char c;
    char *s=new char[100];int a[100][100],b[100][100];
    cin>>na>>nb;
    for(int i=0;i<na;i++)
    {
        scanf("%s",s);k=1;
        for(int j=0;j<strlen(s);j++)
        {
            a[i+1][k++]=s[j]-'0';//cout<<a[j+1][k-1]<<" ";
        }
    }

    cin>>ma>>mb;
    for(int i=0;i<ma;i++)
    {
        scanf("%s",s);k=1;
        for(int j=0;j<strlen(s);j++)
        {
            b[i+1][k++]=(s[j]-'0');//cout<<b[j+1][k-1]<<" ";
        }
    }
    /*for(int i=1;i<=na;i++)
    {
        for(int j=1;j<=nb;j++)
        cout<<a[i][j]<<" ";
        cout<<endl;
    }*/
    max=-5;
    for(int i=-ma;i<=ma;i++)
    {
        for(int j=-mb;j<=mb;j++)
        {
            x=i;y=j;sum=0;//cout<<x<<" "<<y<<endl;
            for(int t=1;t<=na;t++)
            {
                for(int u=1;u<=nb;u++)
                {
                    tt=t+x;uu=u+y;
                    /*if(x==0&&y==1)
                    {
                        cout<<tt<<" "<<uu<<"\t";
                    }*/
                    if((tt>=1&&tt<=ma)&&(uu>=1&&uu<=mb))
                    {
                        sum+=(a[t][u]*b[tt][uu]);
                    }
                }
            }
            if(sum>max){max=sum;//cout<<sum<<" sum"<<endl;
            pi=x;pj=y;}
        }
    }
    cout<<pi<<" "<<pj;
}