#include<bits/stdc++.h>
template <class T>
T inverse(T a, T m) {
    T u=0,v=1;
    while(a!=0){
        T t=m/a;
        m-=t*a;std::swap(a,m);
        u-=t*v;std::swap(u,v);
    }
    assert(m==1);
    return u;
}
template <class T>
class modular {
    public:
        int value;
        constexpr modular() = default;
        constexpr modular(const modular&) = default;
        constexpr modular(modular&&) = default;
        modular& operator=(const modular&) = default;
        modular& operator=(modular&&) = default;
        template <class U>modular (const U& x) {value = normalize(x);}

        template <class U>
            static int normalize(const U& x) {
                int v=static_cast<int>(-mod()<=x&&x<mod()?x:x%mod());
                if(v<0)v+=mod();
                return v;
            }

        template <class U> explicit operator U()const{return static_cast<U>(value);}
        constexpr static auto mod(){return T::value;}

        auto&operator+=(const modular&other) {if((value+=other.value)>=mod())value-=mod();return *this;}
        auto&operator-=(const modular& other){if ((value-=other.value)<0)value+=mod();return *this;}
        template <class U>auto& operator+=(const U& other){return*this+=modular(other);}
        template <class U>auto& operator-=(const U& other){return*this-=modular(other);}
        auto operator-()const{return modular(-value);}
        auto&operator++(){return*this+=1;}
        auto&operator--(){return*this-=1;}
        auto operator++(int){modular result(*this);operator++();return result;}
        auto operator--(int){modular result(*this);operator--();return result;}

        template <class U = T>
            auto&operator*=(const modular&rhs){value=normalize(static_cast<std::int64_t>(value)*static_cast<std::int64_t>(rhs.value));return *this;}
        auto&operator/=(const modular&rhs){return*this*=modular(inverse(rhs.value, mod()));}
};
template<class T>struct is_modular:std::false_type{};
template<class T>struct is_modular <modular<T>>:std::true_type{};
template<class T>constexpr bool is_modular_v=is_modular<T>::value;
template<class T> bool operator==(const modular<T>& lhs, const modular<T>& rhs){return lhs.value==rhs.value;}
template<class T,class U>bool operator==(const modular<T>& lhs, U rhs){return lhs==modular<T>(rhs);}
template<class T,class U>bool operator==(U lhs, const modular<T>& rhs){return modular<T>(lhs)==rhs;}
template<class T> bool operator!=(const modular<T>& lhs, const modular<T>& rhs){return !(lhs == rhs);}
template<class T,class U> bool operator!=(const modular<T>& lhs, U rhs){return !(lhs==rhs);}
template<class T,class U> bool operator!=(U lhs, const modular<T>& rhs){return !(lhs==rhs);}
template<class T> modular<T> operator+(const modular<T>& lhs, const modular<T>& rhs){return modular<T>(lhs)+=rhs;}
template<class T,class U> modular<T> operator+(const modular<T>& lhs, U rhs){return modular<T>(lhs)+=rhs;}
template<class T,class U> modular<T> operator+(U lhs, const modular<T>& rhs){return modular<T>(lhs)+=rhs;}
template<class T> modular<T> operator-(const modular<T>& lhs, const modular<T>& rhs){return modular<T>(lhs)-=rhs;}
template<class T,class U> modular<T> operator-(const modular<T>& lhs, U rhs){return modular<T>(lhs)-=rhs;}
template<class T,class U> modular<T> operator-(U lhs, const modular<T>& rhs){return modular<T>(lhs)-=rhs;}
template<class T> modular<T> operator*(const modular<T>& lhs, const modular<T>& rhs){return modular<T>(lhs)*=rhs;}
template<class T,class U> modular<T> operator*(const modular<T>& lhs, U rhs){return modular<T>(lhs)*=rhs;}
template<class T,class U> modular<T> operator*(U lhs, const modular<T>& rhs){return modular<T>(lhs)*=rhs;}
template<class T> modular<T> operator/(const modular<T>& lhs, const modular<T>& rhs){return modular<T>(lhs)/=rhs;}
template<class T, class U> modular<T> operator/(const modular<T>& lhs, U rhs){return modular<T>(lhs)/=rhs;}
template<class T, class U> modular<T> operator/(U lhs, const modular<T>& rhs){return modular<T>(lhs)/=rhs;}
template<class T, class U>
modular<T> power (const modular<T>& a, U b) {
    assert(b>=0);
    modular<T>x=a,ret=1;
    for (;b>0;b/=2){
        if(b%2==1)ret*=x;
        x*=x;
    }
    return ret;
}
template <class T>std::string to_string(const modular<T>& a) {
    return std::to_string(a.value);
}
template <class T>auto operator<<
(std::ostream& os, const T& a)->std::enable_if_t<is_modular_v<T>, std::ostream&>{
    return os << a.value;
}
template <class T>auto operator>>
(std::istream& is, T& a)-> std::enable_if_t<is_modular_v<T>, std::istream&> {
    long long x;is>>x;
    a=T(x);
    return is;
}

// using mod_type = int;
// struct variable_mod { static mod_type value; };
// mod_type variable_mod::value;
// mod_type& mod = variable_mod::value;
// using mint = modular< variable_mod >;

constexpr int mod = 998'244'353;
using mint = modular<std::integral_constant<std::decay_t<decltype(mod)>, mod>>;


int N;
std::vector<mint>fact,finv;
void init(int n){
    N=n;
    fact.resize(n+1);
    finv.resize(n+1);
    fact.at(0)=1;
    for(int i=1;i<=n;i++)fact.at(i)=fact.at(i-1)*i;
    finv.at(n)=1/fact.at(n);
    for(int i=n;i>=1;i--)finv.at(i-1)=finv.at(i)*i;
    assert(finv.at(0)==1);
}
mint binom(int n,int k){
    assert(0<=n);
    if(k<0||n<k)return 0;
    return fact.at(n)*finv.at(k)*finv.at(n-k);
}

int main(){
    int h,w;std::cin>>h>>w;
    init(2*(h+w)+1);
    std::string sa,sb,sc,sd;std::cin>>sa>>sb>>sc>>sd;
    int A=std::count(sa.begin(),sa.end(),'1');
    int B=std::count(sb.begin(),sb.end(),'1');
    int C=std::count(sc.begin(),sc.end(),'1');
    int D=std::count(sd.begin(),sd.end(),'1');
    if(!A&&!B&&!C&&!D){
        std::cout<<1<<'\n';
        return 0;
    }
    mint ans=0;
    auto cal=[&](int a, int c, int d)->mint{
        if(a==0)return c==0&&d==0;
        return binom(a-1+c+d,a-1);
    };
    for(int ngtkana=0;ngtkana<2;ngtkana++){
        // 縦に貫いている中で最も左のものがこれであるときの、
        // それ以右の場合の数です。
        // そこに c も d もいない場合は累積和の伝播のためだけに使います。
        std::vector<mint>right(w+1);
        int c=0,d=0;
        for(int j=w-1;j>=0;j--){
            right.at(j)=right.at(j+1);
            if(sc.at(j)=='1'||sd.at(j)=='1')
                right.at(j)+=cal(B,c,d);
            if(sc.at(j)=='1'&&sd.at(j)=='1')right.at(j)*=2;
            c+=sc.at(j)=='1';
            d+=sd.at(j)=='1';
        }

        // 縦に貫いている中で最も左がこれであるときの、
        // それよりも左の場合の数と、畳み込んでいきます。
        c=0,d=0;
        for(int j=0;j<w;j++){
            if(sc.at(j)=='1'||sd.at(j)=='1'){
                ans+=cal(A,c,d)*right.at(j);
            }
            c+=sc.at(j)=='1';
            d+=sd.at(j)=='1';
        }
        std::swap(sa,sc);
        std::swap(sb,sd);
        std::swap(A,C);
        std::swap(B,D);
        std::swap(h,w);
    }
    std::cout<<ans<<std::endl;
}


Measured memory_bytes: 4352