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>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
 
using namespace std;
using namespace __gnu_pbds;
 
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define fbo find_by_order
#define ook order_of_key
 
typedef long long ll;
typedef pair<ll,ll> ii;
typedef vector<int> vi;
typedef long double ld; 
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> pbds;
typedef set<int>::iterator sit;
typedef map<int,int>::iterator mit;
typedef vector<int>::iterator vit;

ll ncr[3001][3001];
const int MOD = 1e9 + 7;

ll choose(int n, int r)
{
	if(r==0) return 1;
	if(n<r) return 0;
	if(ncr[n][r]!=-1) return ncr[n][r];
	ncr[n][r]=(choose(n-1,r-1)+choose(n-1,r))%MOD;
	return ncr[n][r];
}

ll dp[3001][3001];
ll modinv[3001];
ll fact[3001];

ll modpow(ll a, ll b)
{
	ll r = 1;
	while(b)
	{
		if(b&1) r=(r*a)%MOD;
		a=(a*a)%MOD;
		b>>=1;
	}
	return r;
}

ll inv(ll a)
{
	return modpow(a,MOD-2);
}

int pre[3001];
int countone(int l, int r)
{
	if(l==0) return pre[r];
	return pre[r]-pre[l-1];
}

int main()
{
	ios_base::sync_with_stdio(0); cin.tie(0);
	memset(ncr,-1,sizeof(ncr));
	for(int i = 1; i <= 3000; i++) modinv[i] = inv(i);
	fact[0]=1;
	for(int i = 1; i <= 3000; i++) fact[i]=(fact[i-1]*i)%MOD;
	int n, m; cin>>n>>m;
	string s; cin >> s;
	for(int i = 0; i < n; i++)
	{
		if(s[i]=='1') pre[i]=1;
		if(i>0) pre[i]+=pre[i-1];
	}
	vector<ii> vec;
	for(int i = 0; i < m; i++)
	{
		int l, r; cin>>l>>r;
		l--; r--;
		vec.pb(mp(l,r));
	}	
	vector<ii> move;
	sort(vec.begin(),vec.end());
	int cur = -1;
	for(int i = 0; i < m; i++)
	{
		if(vec[i].se>cur)
		{
			move.pb(vec[i]);
			cur=vec[i].se;
		}
	}
	move.pb(mp(n,n));
	m = move.size();
	//dp[0][countone(move[0].fi,move[0].se)] = choose(move[0].se-move[0].fi+1, countone(move[0].fi,move[0].se));
	for(int i = 0; i <= n; i++)
	{
		int l = move[0].fi;
		int mid = min(move[1].fi-1, move[0].se);
		int r = move[0].se;
		int cnt = countone(l,r);
		//i is [mid+1,r]
		if(i>cnt) break;
		if(i>r-mid) break;
		dp[0][i] = choose(mid-l+1,cnt-i);
		//cerr<<0<<' '<<i<<' '<<dp[0][i]<<'\n';
	}
	for(int i = 1; i < m - 1; i++)
	{
		int l = move[i].fi;
		int mid = min(move[i+1].fi-1, move[i].se);
		int r = move[i].se;
		int cnt = countone(l,r);
		if(move[i].fi>move[i-1].se)
		{
			ll an = 0;
			for(int j = 0; j <= n; j++)
			{
				an=(an+dp[i-1][j])%MOD;
			}
			for(int j = 0; j <= r-mid; j++)
			{
				if(j>cnt) break;
				dp[i][j] = (an*choose(mid-l+1,cnt-j))%MOD;
			}
		}
		else
		{
			cnt = countone(move[i-1].se+1,r);
			//this is the number of ones in the later part
			//Naive way
			for(int x = 0; x <= r-mid; x++)
			{
				for(int j = n; j >= max(0,x - cnt); j--)
				{
					dp[i][x] = (dp[i][x]+(dp[i-1][j]*choose(mid-l+1,j+cnt-x))%MOD)%MOD;
				}
			}
			/*
			for(int j = n; j >= max(0,r-mid - cnt); j--)
			{
				
				dp[i][x] = (dp[i][x]+(dp[i-1][j]*choose(mid-l+1,j+cnt-x))%MOD)%MOD;
			}
			for(int x = r-mid; x >= 0; x--)
			{
				
			}
			*/
		}
		/*
		for(int j = 0; j <= n; j++)
		{
			cerr<<i<<' '<<j<<' '<<dp[i][j]<<'\n';
		}
		*/
	}
	ll ans = dp[m-2][0];
	cout<<ans<<'\n';
}