Your task is to count the number of permutations of 1, 2, … n that have exactly k inversions (i.e., pairs of elements in the wrong order).
Examples:
Input: n = 4, k = 3
Output: 6
Explanation: For n=4 and k=3, there are 6 permutations that satisfy the given conditions. The permutations are:
- [1, 4, 3, 2]
- [2, 3, 4, 1]
- [2, 4, 1, 3]
- [3, 1, 4, 2]
- [3, 2, 1, 4]
- [4, 1, 2, 3]
Input: n = 5, k = 2
Output: 5
Explanation: For n=5 and k=2, there are 5 permutations that satisfy the given conditions.
Approach:
We can solve this problem using dynamic programming. We'll define a 2D array dp[i][j] to represent the number of the permutations of the first i integers that have exactly j inversions. We can calculate dp[i][j] using the following recurrence relation:
dp[i][j] = ⅀dp[i - 1][j - x] for all x from 0 to i - 1
This recurrence relation represents the fact that to the form a permutation of the first i integers with the j inversions we can fix the position of the integer i and count the number of the permutations of the first i−1 integers with j−x inversions where x is the number of the inversions involving i.
Below is the implementation of the following approach:
#include <iostream>
#include <vector>
using namespace std;
const int MOD = 1e9 + 7;
int main()
{
// Sample Input
int n = 4, k = 3;
vector<int> dp(k + 1, 0);
dp[0] = 1;
// Iterate through the integers from the 1 to n
for (int i = 1; i <= n; ++i) {
vector<int> new_dp(k + 1, 0);
// Iterate through the possible number of the
// inversions from 0 to k
for (int j = 0; j <= k; ++j) {
// Compute the prefix sum
new_dp[j] = (new_dp[j] + dp[j]) % MOD;
if (j > 0) {
// Compute the suffix sum
new_dp[j]
= (new_dp[j] + new_dp[j - 1]) % MOD;
}
// Subtract the prefix sum from suffix sum if
// needed
if (j - i >= 0) {
new_dp[j]
= (new_dp[j] - dp[j - i] + MOD) % MOD;
}
}
dp = new_dp;
}
cout << dp[k] << endl;
return 0;
}
public class Main {
static final int MOD = 1000000007;
public static void main(String[] args)
{
int n = 4, k = 3;
int[] dp = new int[k + 1];
dp[0] = 1;
for (int i = 1; i <= n; ++i) {
int[] newDp = new int[k + 1];
for (int j = 0; j <= k; ++j) {
newDp[j] = (newDp[j] + dp[j]) % MOD;
if (j > 0) {
newDp[j]
= (newDp[j] + newDp[j - 1]) % MOD;
}
if (j - i >= 0) {
newDp[j] = (newDp[j] - dp[j - i] + MOD)
% MOD;
}
}
dp = newDp;
}
System.out.println(dp[k]);
}
}
MOD = 1000000007
def main():
n = 4
k = 3
dp = [0] * (k + 1)
dp[0] = 1
for i in range(1, n + 1):
new_dp = [0] * (k + 1)
for j in range(k + 1):
new_dp[j] = (new_dp[j] + dp[j]) % MOD
if j > 0:
new_dp[j] = (new_dp[j] + new_dp[j - 1]) % MOD
if j - i >= 0:
new_dp[j] = (new_dp[j] - dp[j - i] + MOD) % MOD
dp = new_dp
print(dp[k])
if __name__ == "__main__":
main()
const MOD = 1e9 + 7;
// Sample Input
let n = 4, k = 3;
let dp = new Array(k + 1).fill(0);
dp[0] = 1;
// Iterate through the integers from the 1 to n
for (let i = 1; i <= n; ++i) {
let new_dp = new Array(k + 1).fill(0);
// Iterate through the possible number of the inversions from 0 to k
for (let j = 0; j <= k; ++j) {
// Compute the prefix sum
new_dp[j] = (new_dp[j] + dp[j]) % MOD;
if (j > 0) {
// Compute the suffix sum
new_dp[j] = (new_dp[j] + new_dp[j - 1]) % MOD;
}
// Subtract the prefix sum from the suffix sum if needed
if (j - i >= 0) {
new_dp[j] = (new_dp[j] - dp[j - i] + MOD) % MOD;
}
}
dp = new_dp;
}
console.log(dp[k]);
Output
6
Time Complexity: O(n * k)
Auxiliary Space: O(n)