Description

给定nk,求包含数字1n且恰好有k个逆序对的数组方案数。答案对109+7取模

Constraints

  • 1n1000
  • 0k1000

Solution

dp[i][j]为使用1i构成长度i的数组,且恰有j个逆序对的方案数。这里下标从1开始算起

问题在于怎么做状态转移

如果算出dp[i1]的答案,把数字i插入到原1i1中,则得到dp[i]

而不同位置会产生不同的逆序对,其增加的数目显然在[0,i1]

因此有:dp[i][j]=k=0i1dp[i1][jk]

而这个式子直接算的话需要O(n2k),显然超时,因此加一个前缀和降低复杂度到O(nk)

Note: 如果集合为空,则方案数设为0(i==0

Code

class Solution {
public:
    int kInversePairs(int n, int k) {
        auto dp = vector<vector<long>>(2, vector<long>(k+1));
        auto pre = dp;
        constexpr long MOD = 1e9 + 7;
        for(int i = 1; i <= n; ++i) {
            dp[i & 1][0] = pre[i & 1][0] = 1;
            for(int j = 1; j <= k; ++j) {
                auto sum = pre[i-1 & 1][j];
                if(j-i >= 0) sum -= pre[i-1 & 1][j-i];
                dp[i & 1][j] = (sum + MOD) % MOD;
                pre[i & 1][j] = (pre[i & 1][j-1] + dp[i & 1][j]) % MOD;
            }
        }
        return dp[n & 1][k];
    }
};

LeetCode-629 K Inverse Pairs Array