#include <vector>
#include <array>
#include <functional>
#include <utility>
#include <cstdlib>
#include <algorithm>
#include <iterator>
#include <map>
#include <cstdio>
template<typename T> struct ScanfSpecifier{};
#define DEF(T,V) template<> struct ScanfSpecifier<T>{static constexpr const char* value = V;};
DEF(char*,"%s")DEF(int,"%d")DEF(double,"%lf")DEF(float,"%f")DEF(char,"%c")DEF(const char*,"%s")DEF(unsigned long,"%lu")DEF(unsigned int, "%u")
#ifdef _MSC_VER
DEF(long long int,"%I64d")
#else
DEF(long long int,"%lld")
#endif
#undef DEF
template<typename T> int RD(T& arg){return std::scanf(ScanfSpecifier<T>::value, &arg);}
template<int S> int RD(char (&arg)[S]){return std::scanf("%s", arg);}
int RD(char* arg){return std::scanf("%s", arg);}
template<> int RD<char>(char& arg){return std::scanf(" %c", &arg);}
template<typename T, typename... Args> int RD(T& arg1, Args&... args) {return RD(arg1) + RD(args...);}
template<typename T> T RD(){T ret; RD(ret); return ret;}
template<typename It> void RDV(It begin, It end) { while(begin != end) RD(*begin++); }
template<typename C> void RDV(C& c) {RDV(std::begin(c), std::end(c));}
template<typename T> void WT(T arg) {std::printf(ScanfSpecifier<T>::value, arg); }
template<typename T, typename U> void WT(std::pair<T, U> arg) {std::printf("("); WT(arg.first); std::printf(", "); WT(arg.second); std::printf(")");}
template<typename... Args> void WT(Args... args) { int alc = 0; int dummy[] = {((alc++? std::printf(" "): 0), WT(args), 0)...}; }

template<typename... Args> void WTL(Args... args) { WT(args...); std::printf("\n"); }
template<typename It> void WTV(It begin, It end) { int alc = 0; while(begin != end) (alc++? std::printf(" "): 0), WT(*begin++); }
template<typename C> void WTV(const C& c) {WTV(std::begin(c), std::end(c));}
template<typename It> void WTVL(It begin, It end) { WTV(begin, end); std::printf("\n"); }
template<typename C> void WTVL(const C& c) {WTVL(std::begin(c), std::end(c));}




template<unsigned int Z>
struct ZpZ
{
    static const unsigned int P = Z;
    using U64 = unsigned long long int;
    U64 value;
    ZpZ(long long int n) {if(std::abs(n) >= P)n %= P; if(n < 0)n += P; value = n;}
    ZpZ():value(0){}
    ZpZ& operator+=(ZpZ p){if((value += p.value) >= P)value -= P; return *this;}
    ZpZ& operator-=(ZpZ p){if(value >= p.value)value -= p.value; else value += P - p.value; return *this;}
    ZpZ& operator*=(ZpZ p){value = value * p.value % P; return *this;}
    ZpZ& operator/=(ZpZ p){value = value * p.inverse().value % P; return *this;}
    bool operator==(ZpZ p){return value == p.value;}
    bool operator!=(ZpZ p){return value != p.value;}

#define DEF(op) ZpZ operator op(ZpZ r)const{return ZpZ(value) op##= r;}
DEF(+)DEF(-)DEF(*)DEF(/)
#undef DEF

    explicit operator long long int()const{return value;}
    explicit operator int()const{return value;}
    ZpZ operator-(){return P - value;}
    ZpZ inverse()
    {
        int a = value, b = P, u = 1, v = 0;
        while(b) 
        {
            int t = a / b;
            std::swap(a -= t * b, b); 
            std::swap(u -= t * v, v);
        }
        if(u < 0) u += P;
        return u;
    }
    ZpZ pow(U64 e)
    {
        U64 ret = 1, base = value;
        while(e)
        {
            if((e & 1) && ((ret *= base) >> 32))
                ret %= P;
            if((base *= base) >> 32)
                base %= P;
            e >>= 1;
        }
        return ret;
    }

};

template<unsigned int P>
void WT(ZpZ<P> arg) {WT((int)arg);}





template<typename T>
struct Mapper
{
    int operator[](const T& v) { int& ret = table[v]; if(!ret) rtable[ret = table.size()] = v; return ret - 1; }
    template<typename... Args> int operator()(Args... args) { return (*this)[T(args...)]; }
    T rev(int idx){return rtable[idx + 1];}
    std::map<T, int> table;
    std::map<int, T> rtable;
};

template<typename T, int S>
struct ReferenceArray
{
    struct It {typename std::array<T*, S>::iterator it; T& operator*(){return **it;} void operator++(){it++;} bool operator!=(const It& other){return it != other.it;} };
    int size()const{return _ptr.size();}
    It begin()const{return {_ptr.begin()};}
    It end()const{return {_ptr.end()};}
    T& operator[](int idx)const{return *_ptr[idx];}
    mutable std::array<T*, S> _ptr;
};
template<typename T, typename... Args> 
ReferenceArray<T, sizeof...(Args) + 1> MAKEV(T& arg1, Args&... args) {return {&arg1, &args...};}

struct Range
{   
    struct It {   int num, step; int operator*(){return num;} void operator++(){num += step;} bool operator!=(const It& other){return num != other.num;} };
    Range(int ee):b(0),e(ee){}
    Range(int bb, int ee):b(bb), e(ee){}
    It begin(){return {b, (b < e? 1: -1)};}
    It end(){return {e, 0};}
    int b, e;
};

template<typename T> inline T& UMAX(T& x, T y){if(x < y)x = y; return x;}
template<typename T> inline T& UMIN(T& x, T y){if(y < x)x = y; return x;}
template<typename T, typename... Args> struct ArithmiticPromotion { typedef decltype(T() + typename ArithmiticPromotion<Args...>::type()) type; };
template<typename T, typename U> struct ArithmiticPromotion<T, U> { typedef decltype(T() + U()) type; };
template<typename T> struct ArithmiticPromotion<T, T> { typedef T type; };
template<typename T> struct ArithmiticPromotion<T> { typedef T type; };
template<typename T, typename U> typename ArithmiticPromotion<T, U>::type MAX(T a, U b) { return a < b? b: a; }
template<typename T, typename... Args> typename ArithmiticPromotion<T, Args...>::type MAX(T a, Args... args) { return MAX(a, MAX(args...)); }
template<typename T, typename U> typename ArithmiticPromotion<T, U>::type MIN(T a, U b) { return a < b? a: b; }
template<typename T, typename... Args> typename ArithmiticPromotion<T, Args...>::type MIN(T a, Args... args) { return MIN(a, MIN(args...)); }





//alias
//RD[L],RDV[L],WT[L],WTV[L] for i/o
const int MOD = 1000000007;
using ZZ = ZpZ<MOD>;
ZZ min(ZZ a, ZZ b){return std::min(a.value, b.value);}
ZZ max(ZZ a, ZZ b){return std::max(a.value, b.value);}
using RG = Range;
//template
#include <vector>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <cstdlib>
#include <algorithm>
#include <functional>
using namespace std;

char S[3456];
pair<int, int> qs[3456];

int pre[3456];
ZZ dp[3009][3009];

int one(int l, int r)
{
    return pre[r] - pre[l - 1];
}

int main()
{
    int N, M;
    RD(N, M);
    RD(S + 1);

    S[N + 1] = '0';

    for(int i: RG(1, N + 2))
        pre[i] = pre[i - 1] + (S[i] == '1');


    int total = 0;
    qs[total++] = {0, 0};
    for(int i: RG(M))
    {
        int l, r;
        RD(l, r);

        if(qs[total - 1].second >= r)
            continue;

        while(qs[total - 1].first == l)
            total--;

        while(qs[total - 1].second + 1 < l)
        {
            qs[total] = {qs[total - 1].second + 1, qs[total - 1].second + 1};
            total++;
        }
        qs[total++] = {l, r};
    }
    while(qs[total - 1].second < N + 1)
    {
        qs[total] = {qs[total - 1].second + 1, qs[total - 1].second + 1};
        total++;
    }

    dp[1][one(qs[1].first, qs[1].second)] = 1;

    for(int i = 1, k = 1; i <= N; i++)
    {
        while(i >= qs[k + 1].first)
            k++;
        int l = qs[k].second - i + 1;//qs[k].first + 1;
        for(int o = 0; o <= l; o++)
        {

            int z = l - o;

            if(i + 1 < qs[k + 1].first)
            {
                if(z)
                    dp[i + 1][o] += dp[i][o];
                if(o)
                    dp[i + 1][o - 1] += dp[i][o];
            }
            else
            {
                if(z)
                    dp[i + 1][o + one(qs[k].second + 1, qs[k + 1].second)] += dp[i][o];
                if(o)
                    dp[i + 1][o - 1 + one(qs[k].second + 1, qs[k + 1].second)] += dp[i][o];
            }
        }
    }



    WTL(dp[N + 1][0]);


}






Measured memory_bytes: 70912