You are given an integer n and a 2D array requirements, where requirements[i] = [endi, cnti] represents the end index and the inversion count of each requirement.
A pair of indices (i, j) from an integer array nums is called an inversion if:
i < j and nums[i] > nums[j]
Return the number of permutations perm of [0, 1, 2, ..., n - 1] such that for allrequirements[i], perm[0..endi] has exactly cnti inversions.
Since the answer may be very large, return it modulo10^9 + 7.
Input: n =3, requirements =[[2,2],[1,1],[0,0]]Output: 1Explanation:
The only satisfying permutation is`[2, 0, 1]`:- Prefix `[2, 0, 1]` has inversions `(0, 1)` and `(0, 2)`.- Prefix `[2, 0]` has an inversion `(0, 1)`.- Prefix `[2]` has 0 inversions.
Input: n =2, requirements =[[0,0],[1,0]]Output: 1Explanation:
The only satisfying permutation is`[0, 1]`:- Prefix `[0]` has 0 inversions.- Prefix `[0, 1]` has an inversion `(0, 1)`.
We want to count the number of permutations of [0, 1, ..., n-1] such that for each prefix ending at endi, the number of inversions is exactly cnti. This is a classic DP on permutations with inversion count, but with additional prefix constraints.
classSolution:
defcountInversions(self, n: int, requirements: list[list[int]]) -> int:
MOD =10**9+7 req = [-1]*n
for endi, cnti in requirements:
req[endi] = cnti
max_inv = n*(n-1)//2 dp = [0]*(max_inv+1)
dp[0] =1for i in range(1, n+1):
ndp = [0]*(max_inv+1)
pre = [0]*(max_inv+2)
for k in range((i-1)*(i-2)//2+1):
pre[k+1] = (pre[k] + dp[k]) % MOD
for k in range(i*(i-1)//2+1):
l = max(0, k-(i-1))
r = min(k, (i-1)*(i-2)//2)
if l > r: continue ndp[k] = (pre[r+1] - pre[l]) % MOD
if req[i-1] !=-1:
tmp = [0]*(max_inv+1)
tmp[req[i-1]] = ndp[req[i-1]]
ndp = tmp
dp = ndp
return sum(dp) % MOD
classSolution {
publicintcountInversions(int n, int[][] requirements) {
int MOD = 1_000_000_007;
int[] req =newint[n];
Arrays.fill(req, -1);
for (int[] r : requirements) req[r[0]]= r[1];
int maxInv = n*(n-1)/2;
int[] dp =newint[maxInv+1];
dp[0]= 1;
for (int i = 1; i <= n; ++i) {
int[] ndp =newint[maxInv+1];
int[] pre =newint[maxInv+2];
for (int k = 0; k <= (i-1)*(i-2)/2; ++k) pre[k+1]= (pre[k]+ dp[k]) % MOD;
for (int k = 0; k <= i*(i-1)/2; ++k) {
int l = Math.max(0, k-(i-1)), r = Math.min(k, (i-1)*(i-2)/2);
if (l > r) continue;
ndp[k]= (pre[r+1]- pre[l]+ MOD) % MOD;
}
if (req[i-1]!=-1) {
int[] tmp =newint[maxInv+1];
tmp[req[i-1]]= ndp[req[i-1]];
ndp = tmp;
}
dp = ndp;
}
int ans = 0;
for (int v : dp) ans = (ans + v) % MOD;
return ans;
}
}
classSolution {
funcountInversions(n: Int, requirements: Array<IntArray>): Int {
val MOD = 1_000_000_007
val req = IntArray(n) { -1 }
for ((endi, cnti) in requirements) req[endi] = cnti
val maxInv = n*(n-1)/2var dp = IntArray(maxInv+1)
dp[0] = 1for (i in1..n) {
val ndp = IntArray(maxInv+1)
val pre = IntArray(maxInv+2)
for (k in0..(i-1)*(i-2)/2) pre[k+1] = (pre[k] + dp[k]) % MOD
for (k in0..i*(i-1)/2) {
val l = maxOf(0, k-(i-1))
val r = minOf(k, (i-1)*(i-2)/2)
if (l > r) continue ndp[k] = (pre[r+1] - pre[l] + MOD) % MOD
}
if (req[i-1] != -1) {
val tmp = IntArray(maxInv+1)
tmp[req[i-1]] = ndp[req[i-1]]
for (j in0..maxInv) ndp[j] = tmp[j]
}
dp = ndp
}
return dp.sum() % MOD
}
}