#include <bits/stdc++.h>
using namespace std;
template<typename T = int, T mod = 1'000'000'007, typename U = long long>
struct umod{
        T val;
        umod(): val(0){}
        umod(U x){ x %= mod; if(x < 0) x += mod; val = x;}
        umod& operator += (umod oth){ val += oth.val; if(val >= mod) val -= mod; return *this; }
	umod& operator -= (umod oth){ val -= oth.val; if(val < 0) val += mod; return *this; }
	umod& operator *= (umod oth){ val = ((U)val) * oth.val % mod; return *this; }
	umod& operator /= (umod oth){ return *this *= oth.inverse(); }
        umod& operator ^= (U oth){ return *this = pwr(*this, oth); }
	umod operator + (umod oth) const { return umod(*this) += oth; }
	umod operator - (umod oth) const { return umod(*this) -= oth; }
	umod operator * (umod oth) const { return umod(*this) *= oth; }
	umod operator / (umod oth) const { return umod(*this) /= oth; }
        umod operator ^ (U oth) const { return umod(*this) ^= oth; }
	bool operator < (umod oth) const { return val < oth.val; }
	bool operator > (umod oth) const { return val > oth.val; }
	bool operator <= (umod oth) const { return val <= oth.val; }
	bool operator >= (umod oth) const { return val >= oth.val; }
	bool operator == (umod oth) const { return val == oth.val; }
	bool operator != (umod oth) const { return val != oth.val; }
        umod pwr(umod a, U b) const { umod r = 1; for(; b; a *= a, b >>= 1) if(b&1) r *= a; return r; }
        umod inverse() const {
		U a = val, b = mod, u = 1, v = 0;
		while(b){
			U t = a/b;
			a -= t * b; swap(a, b);
			u -= t * v; swap(u, v);
		}
		if(u < 0)
			u += mod;
		return u;
        }
};
using U = umod<int, 998244353>;
template<typename U>
struct NCR {
        vector<U> fact, ifact;
        NCR(int size){
                fact.resize(size + 1); ifact.resize(size + 1);
                fact[0] = 1;
                for(int i = 1; i <= size; i++) fact[i] = fact[i - 1] * i;
                ifact[size] = fact[size].inverse();
                for(int i = size - 1; i >= 0; i--) ifact[i] = ifact[i + 1] * (i + 1);
        }
        U coef(int n, int r){
                if(n < r) return 0;
                return fact[n] * ifact[r] * ifact[n - r];
        }
};
const int maxn = 500500;
U pref[maxn], suff[maxn], p2[maxn];
int main(){
	NCR<U> ncr(maxn);
	int n, m; cin >> n >> m;
	string a, b, c, d; cin >> a >> b >> c >> d;
	U ans = 0;
	for(int r = 0; r < 2; r++){
		{
			int y = count(c.begin(), c.end(), '1');
			int x = 0, z = 0;
			pref[0] = 1;
			for(int i = 0; i < n; i++){
				x += a[i] == '1';
				z += b[i] == '1';
				if(x + z + y == 0)
					pref[i + 1] = 1;
				else
					pref[i + 1] = ncr.coef(x + y + z - 1, x + z);
			}
		}
		{
			int y = count(d.begin(), d.end(), '1');
			int x = 0, z = 0;
			suff[n] = 1;
			for(int i = n - 1; i >= 0; i--){
				x += a[i] == '1';
				z += b[i] == '1';
				if(x + z + y == 0)
					suff[i] = 1;
				else
					suff[i] = ncr.coef(x + y + z - 1, x + z);
			}
		}
		p2[n] = 1;
		for(int i = n - 1; i >= 0; i--){
			p2[i] = p2[i + 1];
			if(a[i] == '1' && b[i] == '1'){
				p2[i] *= 2;
			}
		}
		U sum = 0;
		for(int i = n - 1; i >= 0; i--){
			if(a[i] == '1' || b[i] == '1'){
				sum += suff[i + 1] * p2[i + 1].inverse();
				ans += pref[i] * sum * p2[i];
			}
		}
		swap(a, c);
		swap(b, d);
		swap(n, m);
	}
	int p = count(a.begin(), a.end(), '0') + count(b.begin(), b.end(), '0') + count(c.begin(), c.end(), '0') + count(d.begin(), d.end(), '0');
	if(p == 2 * n + 2 * m) ans = 1;
	cout << ans.val << endl;
	return 0;
}


Measured memory_bytes: 10624