#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using u32 = uint32_t;
using vi = vector<int>;    using vvi = vector<vi>;
using vb = vector<bool>;   using vvb = vector<vb>;
using vl = vector<ll>;     using vvl = vector<vl>;
using vd = vector<double>; using vvd = vector<vd>;

#define REP(i,n) for(auto i = 0 * (n), i##_len = (n); i < i##_len; ++i)
#define ALL(c) (c).begin(), (c).end()
#define FOR(i,s,n) for(ll i=s, i##_len=(ll)(n); i<i##_len; ++i)
#define TEN(x) ((ll)1e##x)
const ll mod = TEN(9) + 7;
// Segment Tree : 時間計算量 O(n log n), 空間計算量 O(n)
// require  : なし
// verified : 
//
// T はモノイド（単位元を持ち，結合則が成り立つ）であることが要求される
template <class T, class U = size_t>
struct SegTree {
	// !!! 実装時 t(lhs, rhs) の引数の順番に注意(意図せず可換則が要求されてしまう) !!!
	typedef typename T::V V;
	explicit SegTree(U _n = 0, const T &t = T()) : n(1), t(t) {
		while (n < _n) n *= 2;
		v.assign(n * 2 - 1, t.identity());
		if (n >= 2) {
			for (U i = n - 2;; --i) {
				v[i] = t(v[i * 2 + 1], v[i * 2 + 2]);
				if (i == 0) break; // Uが符号無し整数の可能性がある為こう実装している
			}
		}
	}
	V operator[](U i) const { return v[n - 1 + i]; }
	void set(U i, const V & x) {
		i += n - 1;
		v[i] = x;
		while (i > 0) {
			i = (i - 1) / 2;
			v[i] = t(v[i * 2 + 1], v[i * 2 + 2]);
		}
	}
	// [a,b)の範囲についてのクエリを返す
	V get(U a, U b) const { return q(a, b, 0, 0, n); }
private:
	// t : traits のインスタンス
	// v : 完全二分木の配列表現
	// n : 完全二分木の葉の数
	T t;
	vector<V> v;
	U n;

	// [a,b)の範囲についてのクエリを返す
	// k     : 現在見ている接点の番号
	// [l,r) : kに対応した範囲 
	V q(U a, U b, U k, U l, U r) const {
		if (r <= a || b <= l) return t.identity(); // 範囲外
		if (a <= l && r <= b) return v[k];         // [l,r) ⊂ [a,b)
		//[l,r)の一部が[a,b)に含まれる
		U c = (l + r) / 2;
		return t(
			q(a, b, k * 2 + 1, l, c),
			q(a, b, k * 2 + 2, c, r)
		);
	}
};

template <class T>
struct SumTrait {
	typedef T V;
	V identity() const { return 0; }
	V operator()(const V &a, const V &b) const { return a + b; }
};


template<int64_t mod> struct GF {
	typedef int64_t T;
	T v;
	GF() = default;
	GF(T v) : v((v % mod + mod) % mod) {}
	GF & operator+=(GF x) { v = (v + x.v) % mod; return *this; }
	GF & operator*=(GF x) { v = (v * x.v) % mod; return *this; }
	GF & operator-=(GF x) { v = (v - x.v + mod) % mod; return *this; }
	GF & operator/=(GF x) { return (*this) *= x.inverse(); }
	GF operator+(GF rhs) const { GF lhs = *this; return lhs += rhs; }
	GF operator*(GF rhs) const { GF lhs = *this; return lhs *= rhs; }
	GF operator-(GF rhs) const { GF lhs = *this; return lhs -= rhs; }
	GF operator/(GF rhs) const { GF lhs = *this; return lhs /= rhs; }
	GF inverse() const { // http://topcoder.g.hatena.ne.jp/iwiwi/20130105/1357363348
		T a = v, b = mod, x = 1, y = 0;
		while (b) {
			T t = a / b;
			swap(a -= t * b, b);
			swap(x -= t * y, y);
		}
		return x;
	}
	GF pow(T n) const {
		GF r; r.v = 1;
		for (T x = v; n > 0; n >>= 1) {
			if (n & 1) (r.v *= x) %= mod;
			(x *= x) %= mod;
		}
		return r;
	}
	typedef size_t U;
	static GF fact(U n) {
		static vector<GF> data;
		U m = data.size();
		if (m <= n) {
			data.resize(n + 1);
			if (m == 0) { data[0].v = 1; m++; }
			for (U i = m; i < n + 1; ++i) data[i] = data[i - 1] * i;
		}
		return data[n];
	}
	static GF nCr(U n, U r) { return fact(n) / fact(r) / fact(n - r); }
	static GF nPr(U n, U r) { return fact(n) / fact(r); }
};

int main() {
#ifdef INPUT_FROM_FILE
	ifstream cin("sample.in");
	ofstream cout("sample.out");
#endif
	cin.tie(0);
	ios_base::sync_with_stdio(false);
	cout << fixed << setprecision(50);

	ll n, m; cin >> n >> m;
	string S;
	vl L, R;
	{ // 関係ない部分の除去
		string s; cin >> s;
		vl l(m), r(m); 
		REP(i, m) {
			cin >> l[i] >> r[i];
			l[i]--; r[i]--;
		}

		vl imos(n + 1, 0);
		REP(i, m) {
			imos[l[i]]++;
			imos[r[i] + 1]--;
		}
		FOR(i, 1, n + 1) imos[i] += imos[i - 1];

		SegTree<SumTrait<ll>> st(n);
		REP(i, n) if (imos[i] > 0) {
			st.set(i, 1);
			S.push_back(s[i]);
		}
		ll mar = 0;
		REP(i, m) if (mar < st.get(0, r[i] + 1)) {
			if (i > 0 && L.back() == st.get(0, l[i] + 1) - 1) {
				R.back() = mar = st.get(0, r[i] + 1);
			} else {
				L.push_back(st.get(0, l[i] + 1) - 1);
				R.push_back(mar = st.get(0, r[i] + 1));
			}
		}
	}

	const ll N = S.size(), M = R.size();
	SegTree<SumTrait<ll>> zero(N), one(N);
	REP(i, N) (S[i] == '0' ? zero : one).set(i, 1);
	
	ll maxzero = zero.get(0, N + 1);
	vvl dp(M + 1, vl(maxzero + 1, -1));
	dp[0][0] = 1;
	REP(i, M) REP(j, maxzero + 1) if(dp[i][j] != -1){
		ll k = L[i] - j; // 使った1の数
		ll range = (i == M - 1 ? R[i] : L[i + 1]) - L[i];
		ll zeroma = zero.get(0, R[i]) - j;
		ll onema = one.get(0, R[i]) - k;
		FOR(l, max(0ll, range - onema), min(range, zeroma) + 1) {
			if (l + j > maxzero) continue;
			auto x = GF<mod>::nCr(range, l) * dp[i][j];
			if (dp[i + 1][l + j] == -1) dp[i + 1][l + j] = x.v;
			else dp[i + 1][l + j] = (GF<mod>(dp[i + 1][l + j]) + x).v;
		}
	}
	
	cout << dp[M][maxzero] << endl;

	return 0;
}

Measured memory_bytes: 15488