Problem:
Score : 900 points

Problem Statement

There is a string S of length N consisting of characters 0 and 1. You will perform the following operation for each i = 1, 2, ..., m:

Arbitrarily permute the characters within the substring of S starting at the l_i-th character from the left and extending through the r_i-th character.

Here, the sequence l_i is non-decreasing.

How many values are possible for S after the M operations, modulo 1000000007(= 10^9+7)?

Constraints

2≦N≦3000

1≦M≦3000

S consists of characters 0 and 1.

The length of S equals N.

1≦l_i < r_i≦N

l_i ≦ l_{i+1}

Input

The input is given from Standard Input in the following format:

N M
S
l_1 r_1
:
l_M r_M

Output

Print the number of the possible values for S after the M operations, modulo 1000000007.

Sample Input 1

5 2
01001
2 4
3 5

Sample Output 1

6

After the first operation, S can be one of the following three: 01001, 00101 and 00011.

After the second operation, S can be one of the following six: 01100, 01010, 01001, 00011, 00101 and 00110.

Sample Input 2

9 3
110111110
1 4
4 6
6 9

Sample Output 2

26

Sample Input 3

11 6
00101000110
2 4
2 3
4 7
5 6
6 10
10 11

Sample Output 3

143

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>

#define VARNAME(x) #x
#define show(x) cerr << #x << " = " << x << endl

using namespace std;
using ll = long long;
using ld = long double;
template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v)
{
    os << "sz:" << v.size() << "\n[";
    for (const auto& p : v) {
        os << p << ",";
    }
    os << "]\n";
    return os;
}
template <typename S, typename T>
ostream& operator<<(ostream& os, const pair<S, T>& p)
{
    os << "<" << p.first << "," << p.second
       << ">";
    return os;
}

constexpr ll MOD = 1000000007LL;

template <typename T>
constexpr T INF = numeric_limits<T>::max() / 10;


class Modulo
{
public:
    Modulo(const ll n, const ll mod = MOD) : size{n + 1}, mod{mod}, fact(n + 1, 1), inv(n + 1, 1), inv_fact(n + 1, 1)  // mod should be prime
    {
        for (ll i = 2; i <= n; i++) {
            fact[i] = (fact[i - 1] * i) % mod;
            inv[i] = ((mod - (mod / i)) * inv[mod % i]) % mod;
            inv_fact[i] = (inv_fact[i - 1] * inv[i]) % mod;
        }
    }
    ll factorial(const ll n) const
    {
        assert(n < size);
        return fact[n];
    }
    ll inverse(const ll n) const
    {
        assert(n < size);
        return inv[n];
    }
    ll inverseFactorial(const ll n) const
    {
        assert(n < size);
        return inv_fact[n];
    }
    ll permutation(const ll n, const ll k) const
    {
        assert(n < size);
        assert(k <= n);
        return (fact[n] * inv_fact[n - k]) % mod;
    }
    ll combination(const ll n, const ll k) const
    {
        assert(n < size);
        assert(k <= n);
        return (((fact[n] * inv_fact[k]) % mod) * inv_fact[n - k]) % mod;
    }
    ll homogenious(const ll n, const ll k) const { return (n == 0 and k == 0 ? 1 : combination(n + k - 1, k)); }

private:
    const ll size;
    const ll mod;
    vector<ll> fact;
    vector<ll> inv;
    vector<ll> inv_fact;
};

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    ll N, M;
    cin >> N >> M;
    string S;
    cin >> S;
    vector<vector<ll>> tmp(3001);
    for (ll i = 0; i < M; i++) {
        ll l, r;
        cin >> l >> r;
        l--, r--;
        if (tmp[l].size() > 0) {
            if (tmp[l][0] < r) {
                tmp[l][0] = r;
            }
        } else {
            tmp[l].push_back(r);
        }
    }
    using P = pair<ll, ll>;
    vector<P> R;
    ll r = 0;
    for (ll i = 0; i <= 3000; i++) {
        if (tmp[i].size() > 0 and tmp[i][0] > r) {
            R.push_back({i, tmp[i][0]});
            r = tmp[i][0];
        }
    }
    const ll size = R.size();
    vector<P> intersect(size);
    intersect[0] = {-1, -1};
    for (ll i = 1; i < size; i++) {
        if (R[i].first > R[i - 1].second) {
            intersect[i] = {R[i].first, R[i].first - 1};
        } else {
            intersect[i] = {R[i].first, R[i - 1].second};
        }
    }
    intersect.push_back({N, N});
    vector<ll> one(size + 1, 0);
    vector<ll> one_orig(size, 0);
    for (ll i = 0; i < size; i++) {
        if (i == 0) {
            one[i] = 0;
        } else {
            for (ll j = intersect[i].first; j <= intersect[i].second; j++) {
                one[i] += (S[j] == '1' ? 1 : 0);
            }
        }
        for (ll j = R[i].first; j <= R[i].second; j++) {
            one_orig[i] += (S[j] == '1' ? 1 : 0);
        }
    }
    Modulo mod(N + 1);
    vector<ll> dp(N + 1, 0);  // i番目の区間
    dp[0] = 1;
    for (ll i = 0; i < size; i++) {
        vector<ll> tmp(N + 1, 0);
        for (ll j = 0; j <= intersect[i].second - intersect[i].first + 1; j++) {
            if (dp[j] > 0) {
                const ll tot = one_orig[i] - one[i] + j;
                const ll next = intersect[i + 1].second - intersect[i + 1].first + 1;
                const ll rest = R[i].second - R[i].first + 1 - next;
                for (ll k = max(0LL, tot - rest); k <= min(tot, next); k++) {
                    (tmp[k] += mod.combination(rest, tot - k) * dp[j] % MOD) %= MOD;
                }
            }
        }
        dp = tmp;
    }
    ll ans = 0;
    for (ll i = 0; i <= N; i++) {
        (ans += dp[i]) %= MOD;
    }
    cout << ans << endl;

    return 0;
}