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

// macros
#define overload_rep(va_0, va_1, va_2, name, ...) name
#define rep_0(i, n) for(int i = 0; i < (n); ++i)
#define rep_1(i, x, y) for(int i = (x); i <= (y); ++i)
#define rep(...) overload_rep(__VA_ARGS__, rep_1, rep_0)(__VA_ARGS__)
#define all(a) a.begin(), a.end()
#ifndef STOP_DEBUG
#define debug(...)\
    do { cerr << boolalpha << "[" << #__VA_ARGS__ << "]:";\
    debug_cerr(__VA_ARGS__); cerr << noboolalpha; } while (0)
#else
#define debug(...)
#endif

// functions
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
void debug_cerr(){ cerr << '\n'; }
template<class Head, class... Tail>
void debug_cerr(Head head, Tail... tail){
    cerr << ' ' << head;
    debug_cerr(tail...);
}

// cin/cout setup
struct IoSetup{
    IoSetup(){
        cin.tie(nullptr);
        ios::sync_with_stdio(false);
        cout << fixed << setprecision(20);
    }
} iosetup;

// libraries
template<const int_fast64_t mod = 1000000007>
struct ModInt {
private: using ll = int_fast64_t;
public: ll x;
    constexpr ModInt(ll t = 0) noexcept : x((t %= mod) < 0 ? t + mod : t) {}
    constexpr friend istream& operator >> (istream& s, ModInt& m) noexcept {
        s >> m.x; m.x %= mod; if(m.x < 0)m.x += mod; return s;
    }
    constexpr friend ostream& operator << (ostream& s, ModInt m) noexcept {
        return s << m.x;
    }
    constexpr ModInt operator + (const ModInt m) noexcept { return ModInt(*this) += m; }
    constexpr ModInt& operator += (const ModInt m) noexcept {
        if((x += m.x) >= mod)x -= mod; return *this;
    }
    constexpr ModInt operator - (const ModInt m) noexcept { return ModInt(*this) -= m; }
    constexpr ModInt& operator -= (const ModInt m) noexcept {
        if((x += mod - m.x) >= mod)x -= mod; return *this;
    }
    constexpr ModInt operator * (const ModInt m) noexcept { return ModInt(*this) *= m; }
    constexpr ModInt& operator *= (const ModInt m) noexcept {
        x = x * m.x % mod; return *this;
    }
    constexpr ModInt operator / (const ModInt m) noexcept { return ModInt(*this) /= m; }
    constexpr ModInt& operator /= (const ModInt m) noexcept {
        return *this *= m.inv();
    }
    constexpr ModInt inv() const noexcept {
        return pow(mod - 2);
    }
    constexpr ModInt pow(ll p) const noexcept {
        ModInt res(1), mult(*this);
        for(; p; p >>= 1){ if(p & 1)res *= mult; mult *= mult; }
        return res;
    }
};

template<const int_fast64_t mod = 1000000007>
struct ModFact {
private:
    using mint = ModInt<mod>;
    vector<mint> fact, ifact;
public:
    constexpr ModFact(int sz = 200000) noexcept : fact(sz + 1), ifact(sz + 1) {
        fact[0] = mint(1);
        for(int i = 1; i <= sz; ++i)fact[i] = fact[i - 1] * mint(i);
        ifact[sz] = fact[sz].inv();
        for(int i = sz; i > 0; --i)ifact[i - 1] = ifact[i] * mint(i);
    }
    constexpr mint operator [] (int id) const noexcept { return fact[id]; }
    constexpr mint operator () (int n, int r) noexcept {
        return fact[n] * ifact[n - r] * ifact[r];
    }
    constexpr mint nPr(int n, int r) noexcept {
        return fact[n] * ifact[r];
    }
    constexpr mint inv(int id) const noexcept { return ifact[id]; }
};

// declarations
using mint = ModInt<>;
using mfact = ModFact<>;

int N, M;
int cnt[3010];
int ls[3010], rs[3010];
int L[3010], R[3010];
mint dp[3010][3010];
mfact fact;

// solve
int main(){

    int N, M;
    cin >> N >> M;

    rep(i, N){
        char c; 
        cin >> c;
        if(c == '1')cnt[i + 1]++;
        cnt[i + 1] += cnt[i];
    }

    rep(i, M){
        cin >> ls[i] >> rs[i];
        ls[i]--;
    }

    int size_q = 0, pos = 0, last_r = 0;
    while(pos < M){
        int l = ls[pos], r = rs[pos++];
        if(last_r >= r)continue;
        for(; pos < M; pos++){
            if(ls[pos] > l)break;
            chmax(r, rs[pos]);
        }
        L[size_q] = l;
        R[size_q++] = last_r = r;
    }

    L[size_q] = N;
    dp[L[0]][cnt[L[0]]] = mint(1);
    rep(i, size_q){
        int l = L[i], r = min(R[i], L[i + 1]);
        rep(j, 0, N){
            int usable = cnt[R[i]] - j;
            if(usable < 0)break;
            int mi = max(0, r - (R[i] - usable)), ma = min(r - l, usable);
            rep(k, mi, ma){
                dp[r][j + k] += dp[l][j] * fact(r - l, k);
            }
        }
        int until_next = cnt[L[i + 1]] - cnt[r];
        rep(j, 0, N){
            if(j + until_next > N)break;
            dp[L[i + 1]][j + until_next] = dp[r][j];
        }
    }

    cout << dp[N][cnt[N]] << '\n';
    return 0;

}


Measured memory_bytes: 72448