Good one.. marked as DP, so I was striking to work out a DP formula... well, not all DP have a formula - one type of DP is called memorized search: there's no formula, only previous calculated results can be reused..
I learnt from vivmbbs21's code:
#include <vector> #include <iostream> using namespace std; #define MOD 1000000007 #define REP(i,s,e) for(int i = s; i < e; i ++) vector<vector<int>> cr(302, vector<int>(302)); vector<vector<vector<int>>> memo(102, vector<vector<int>>(102, vector<int>(302))); int solve(int d, int x, int m) { if (x <= 0 || x > d) return 0; if (m == 0) return 1; if (memo[d][x][m] != -1) return memo[d][x][m]; return memo[d][x][m] = (solve(d, x - 1, m - 1) + solve(d, x + 1, m - 1)) % MOD; } vector<vector<int>> memo2(10, vector<int>(302)); int solve2(int k, int n, int m, vector<int> &x, vector<int> &d) { if (k == n) return m == 0 ? 1 : 0; if (memo2[k][m] != -1) return memo2[k][m]; int ret = 0; REP(i, 0, m + 1) // at row k, for all possible steps to take { long long cret = 1LL * solve(d[k], x[k], i) * cr[m][i] % MOD; ret += cret * solve2(k + 1, n, m - i, x, d) % MOD; if (ret >= MOD) ret -= MOD; } return memo2[k][m] = ret; } int main() { // Pascal's Triangle REP(i, 0, 302) { cr[i][0] = cr[i][i] = 1; REP(j, 1, i) cr[i][j] = (cr[i - 1][j] + cr[i - 1][j - 1]) % MOD; } vector<vector<vector<int>>> init(102, vector<vector<int>>(102, vector<int>(302, -1))); memo = init; // int t; cin >> t; while (t--) { vector<vector<int>> init2(10, vector<int>(302, -1)); memo2 = init2; int n, m; cin >> n >> m; vector<int> d(n), x(n); REP(i, 0, n) cin >> x[i]; REP(i, 0, n) cin >> d[i]; int ret = solve2(0, n, m, x, d); cout << ret << endl; } }