Problem:
D : Hopping Hearts / こころぴょんぴょん

問題文

N 羽のうさぎが長さ L−1 の平均台の上にいる。 i 番目のうさぎの初期位置は整数 x_iであり、 0 ≤ x_{i} \lt x_{i+1} ≤ L−1 を満たす。座標は右に進むほど大きくなる。任意の i 番目のうさぎは、任意の回数だけ、ちょうど距離 a_i だけ右方向にジャンプ(すなわち、x_i から x_i+a_i へ移動)することができる。ただし別のうさぎを飛び越えること、−1 以下または L 以上の位置に入ることはできない。また、同時にジャンプしていられるのは高々 1 羽であり、ある座標に存在できるうさぎの数も高々 1 羽である。

初期状態から始めてジャンプを任意の回数繰り返したあとの x_{0}, …, x_{N−1} の状態として、あり得るものは何通りあるか。1\,000\,000\,007 で割った余りで求めよ。

入力

入力は以下の形式で与えられる。

N L
x_{0} … x_{N−1}
a_{0} … a_{N−1}

制約

入力はすべて整数である

1 \≤ N \≤ 5\,000

N \≤ L \≤ 5\,000

0 \≤ x_{i} \lt x_{i+1} \≤ L−1

0 \≤ a_{i} \≤ L−1

出力

答えを1行で出力せよ。

サンプル

サンプル入力1

1 3
0
1

サンプル出力1

3

1/0でうさぎがいる/いないを表現すれば、100, 010, 001 の 3 通りである。

サンプル入力2

2 4
0 1
1 2

サンプル出力2

4

1100, 1001, 0101, 0011 の 4 通りである。

サンプル入力3

10 50
0 1 2 3 4 5 6 7 8 9
1 1 1 1 1 1 1 1 1 1

サンプル出力3

272278100

二項係数 C(50,10) = 10\,272\,278\,170 であり、それを 1\,000\,000\,007 で割ったあまりは 272\,278\,100 である。

Solution in C++14 (judge verdict: Time Limit Exceeded)

#include <bits/stdc++.h>
  
using namespace std;
  
#define rep(i,n) REP(i,0,n)
#define REP(i,s,e) for(int i=(s); i<(int)(e); i++)
#define repr(i, n) REPR(i, n, 0)
#define REPR(i, s, e) for(int i=(int)(s-1); i>=(int)(e); i--)
#define pb push_back
#define all(r) r.begin(),r.end()
#define rall(r) r.rbegin(),r.rend()
#define fi first
#define se second
  
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const int INF = 1e9;
const ll MOD = 1e9 + 7;
double EPS = 1e-8;

const int MAX_N = 5010;

ll d[MAX_N];

int main(){
	int n, L;
	scanf("%d %d", &n, &L);
	vi x(n), a(n);
	rep(i, n) scanf("%d", &x[i]);
	rep(i, n) scanf("%d", &a[i]);
	{
		for(int i = x.back(); i < L; i += a.back()) {
			d[i] = 1;
		}
	}
	repr(i, n-1) {
		ll sum = 0LL;
		rep(j, L) (sum += d[j]) %= MOD;
		rep(j, L) {
			if(j < x[i] || (j - x[i]) % a[i] != 0 || j >= L - (n-1-i)) {
				sum -= d[j];
				(sum += MOD) %= MOD;
				d[j] = 0;
			}
			else {
				sum -= d[j];
				(sum += MOD) %= MOD;
				d[j] = sum;
			}
		}
	}
	ll ans = 0LL;
	rep(i, L) (ans += d[i]) %= MOD;
	cout << ans << endl;
	return 0;
}