Job
Written by Mohamed Boukerche
Problem Statement
1. Observations
- We are given 2 integers
NandC, consider permutations of sizeNand the incorrectness of a permutation is the number of inversions, more formally the count of pairs(i, j)withi < jandA[i] > A[j]. - We should count how many permutations of length
Nhave exactlyCinversions with modulo
2. Idea
- Suppose we already have a permutation of size
i - 1, and now we want to insert the elementi. - Depending on where we insert it, we add between
0andi - 1new inversions:- Insert at the end → add
0inversions - Insert before the last element → add
1inversion - Insert at the front → add
i - 1inversions.
- Insert at the end → add
Thus the number of inversions grows predictably.
This can be solved with Dynamic Programming (DP)
3. DP
Definition
We define: number of permutations of length i with exactly j inversions.
Transition
If we add the element i and place it such that it creates k new inversions, then the previous part must have j - k inversions.
Base Case
4. Optimization with Prefix Sums
- Naively, each transition costs , giving
- Using this naive approach may get partial points (~70%) because it is not efficient enough and optimizing the DP is necessary for full score.
- We can speed this up with prefix sums:
Where:
This reduces the complexity to .
5. Algorithm
- Initialize
dp[0] = 1(only one empty permutation). - For each new number in 2..N:
- Compute prefix sums of the current
dp. - Use them to fill the new
dp.
- Print the answer
dp[C]and don't forget modulo .
6. Implementation (C++)
cpp
/*
* Job problem by Mohamed boukerche
*/
#include <bits/stdc++.h>
using namespace std;
const int MOD = 1e9 + 7;
#define ll long long
#define fastAOI ios::sync_with_stdio(false); cin.tie(nullptr);
int main() {
fastAOI;
ll n, c; cin >> n>> c;
vector<ll> dp(c + 5); // For safety
dp[0] = 1;
vector<ll> a(c + 5);
for (int i = 2; i <= n; i++) {
vector<ll> pre(c + 5);
pre[0] = dp[0];
for(ll j = 1; j <= c; j++){
pre[j] = pre[j - 1] + dp[j];
pre[j] %= MOD;
}
for(int j = 0; j <= c; j++){
ll l = pre[j], r = 0;
if (j - i >= 0) r = pre[j - i];
a[j] = (l - r + MOD) % MOD;
}
a.swap(dp);
}
cout << dp[c];
return 0;
}7. Complexity
- Prefix sums allow each transition to be computed in .
- We have
Nelements andCinversions, so overall:

