Open In App

CSES Solutions – Permutation Inversions

Last Updated : 06 May, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

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:

C++
#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;
}
Java
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]);
    }
}
Python
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()
JavaScript
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)



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads