## Title Description

Difficult questions

Given two integers n and k, find out the number of different arrays that contain numbers from 1 to N and exactly have k reverse pairs.

The definition of reverse order pair is as follows: for the ith and jth elements of the array, if full I < j and a [i] > a [j], it is a reverse order pair; Otherwise not.

Since the answer may be large, you only need to return the value of the answer mod 10^9 + 7.

## Sample

Example 1:

Input: n = 3, k = 0

Output: 1

Explanation:

Only the array [1,2,3] contains integers from 1 to 3 and has exactly 0 reverse pairs.

Example 2:

Input: n = 3, k = 1

Output: 2

Explanation:

Both arrays [1,3,2] and [2,1,3] have a pair in reverse order.

## explain

The range of n is [1,1000] and the range of k is [0,1000].

## thinking

Dynamic programming, using dp array of n+1 * k+1, dp[i][j] represents the number of arrays with length I and reverse order pair j

Initialization, dp[i][0] = 1, arbitrary length, reverse order pair is 0, that is, sequential row

The rest is 0

State transition, consider a slightly longer example, n = 5, k = 1;

Before adding 5, there are many kinds of arrangement of 4, which are not listed one by one. For example, consider 1 2 4 3, 1 2 3 4

When one reverse order pair is required, one is that there is an original reverse order pair, and then 5 is added to the last one, namely dp[4][1];

Or there is no reverse order pair. I use 5 to add an reverse order pair. 5 has_ 1_ 2_ 3_ 4_ Five positions can be inserted

Plug in 3_ Between 4, a reverse order pair will be constructed, and one more forward position will lead to one more reverse order pair, so it is also one, namely dp[4][0];

Therefore, dp[i][j] should be equal to the sum of all qualified dp[i-1][x],

The condition is that the original reverse order pair + insert the new reverse order pair can be equal to j,

At most, i-1 pairs can be added, (1_2_3_4 and 5 are inserted to the end, and 4 pairs in reverse order are added)

Therefore, if it does not exceed the boundary, dp[i][j] = dp[i-1][j-(i-1)] is added to dp[i-1][j];

When the boundary is exceeded, it is added from dp[i-1][0] to dp[i-1][j]

It is strongly recommended that you write with examples

In this way, the time complexity O(n^2 * k) will change TLE for each accumulation

Apply the official transfer formula

Optimized and observed

When it exceeds the boundary, dp[i][j] only adds one dp[i-1][j] more than dp[i][j-1];

Without exceeding the boundary, dp[i][j] is dp[i-1][j] more than dp[i][j-1] and dp[i-1][j-i] less

So you can add and subtract and optimize it to O(nk)

Continue to apply the official formula

In addition, when j is cycled, for example, n = 2 and K = 10, it does not need to be cycled so many times

When i is known, the maximum number of reverse order pairs is determined. When i is in reverse order, the reverse order pairs are the most

For example 4 3 2 1, where 43 42 41 32 31 21 is its reverse order pair, it is found that the law is the accumulation of 1 to 3

Generalization, for i, there are i-1 reverse order pairs; For i-1, there are i-2 reverse order pairs; For 1, there is no reverse order pair

Therefore, the maximum number of inverse pairs of length I is the accumulation of 1 to I-1, that is, (0+i-1)i/2. The sum of the first term plus the last term is divided by two

You can narrow down a portion of the loop

There is also mold taking, which is added in almost every place. It's really annoying

## code

class Solution { public: int kInversePairs(int n, int k) { if(n == 1 && k != 0) return 0; if(k == 0) return 1; int mod = 1000000007; vector<vector<int>> dp(n+1,vector<int>(k+1,0)); for(int i = 1; i <= n; i++) { dp[i][0] = 1; } for(int i = 1; i <= n; i++) { int m = i*(i-1)/2; for(int j = 1; j <= m && j <= k; j++) { if(j < i) { dp[i][j] = (dp[i][j-1]% mod + dp[i-1][j]%mod)% mod; } else dp[i][j] = (dp[i][j-1] + mod) % mod - (dp[i-1][j-i] + mod) % mod + (dp[i-1][j]+ mod) % mod; dp[i][j] = (dp[i][j]% mod + mod) % mod; } } return dp[n][k]; } };

## result

## Add an official explanation

class Solution { private: static constexpr int mod = 1000000007; public: int kInversePairs(int n, int k) { vector<vector<int>> f(2, vector<int>(k + 1)); f[0][0] = 1; for (int i = 1; i <= n; ++i) { for (int j = 0; j <= k; ++j) { int cur = i & 1, prev = cur ^ 1; f[cur][j] = (j - 1 >= 0 ? f[cur][j - 1] : 0) - (j - i >= 0 ? f[prev][j - i] : 0) + f[prev][j]; if (f[cur][j] >= mod) { f[cur][j] -= mod; } else if (f[cur][j] < 0) { f[cur][j] += mod; } } } return f[n & 1][k]; } };

The official space is also optimized. After all, only the previous value is used

## summary

For dynamic programming, we mainly use handwritten examples to understand, and then find laws and optimization