/** * We can use the following algorithm to compute LIS array: * We will have an array 'state' of length 10 with state[i] being the * smallest possible last digit of an increasing subsequence with length * 'i', or INFINITY in case there is no subsequence with length 'i'. * Then we will process the digits one by one, from left to right. Let current * digit be 'd', then we can find maximal i, such that state[i] < d and * LIS[current index] = i + 1 * state[i + 1] = d * Notice that while processing a digit, we don't care about any of the * previous digits, we just use the array 'state', so to solve our problem * we can use dynamic programming on pairs (prefix, state). * 0 <= state[1] < state[2] < state[3] < ... < state[10] <= 9, so, we can use a * bitmask to encode the array 'state' if we treat it as a set. **/ #include using namespace std; const int MX = 1000, md = 1000000007; void add(int& x, int y) { x += y; if (x >= md) x -= md; } // array to store dynamic programming values // dp[i][mask] = count of numbers of length (i + 1) with correct first (i + 1) // values of LIS array having 'state' described by mask int dp[MX][1 << 10]; // mapping from mask to 'state' array int state[1 << 10][11]; int main() { for (int i = 0; i < (1 << 10); i++) { state[i][0] = -1; for (int k = 1; k <= 10; k++) state[i][k] = 9; for (int x = i, j = 0, k = 1; x > 0; x /= 2, j++) if (x & 1) state[i][k++] = j; } int t; scanf("%d", &t); while (t--) { int n, LIS; scanf("%d %d", &n, &LIS); for (int i = 0; i < 10; i++) dp[0][1 << i] = (i > 0 || n == 1 ? 1 : 0); for (int i = 1; i < n; i++) { scanf("%d", &LIS); for (int mask = 0; mask < (1 << 10); mask++) for (int x = state[mask][LIS - 1] + 1; x <= state[mask][LIS]; x++) add(dp[i][mask ^ (1 << state[mask][LIS]) ^ (1 << x)], dp[i - 1][mask]); } int ans = 0; for (int mask = 0; mask < (1 << 10); mask++) add(ans, dp[n - 1][mask]); printf("%d\n", ans); memset(dp, 0, n * sizeof(dp[0])); } return 0; }