【洛谷】P1521 求逆序对

题目地址:

https://www.luogu.com.cn/problem/P1521

题目描述:
我们说 ( i , j ) (i,j) (i,j) a 1 , a 2 , ⋯   , a N a_1,a_2,\cdots,a_N a1,a2,,aN的一个逆序对,当且仅当 i < j i<j i<j a i > a j a_i>a_j ai>aj。例如 [ 2 , 4 , 1 , 3 , 5 ] [2,4,1,3,5] [2,4,1,3,5]的逆序对有 3 3 3个,分别为 ( 1 , 3 ) , ( 2 , 3 ) , ( 2 , 4 ) (1,3),(2, 3), (2, 4) (1,3),(2,3),(2,4)。现在已知 N N N K K K,求 1 , 2 , 3 , ⋯   , N 1,2,3,\cdots,N 1,2,3,,N的所有特定排列,使得这些排列的逆序对的数量恰好为 K K K。输出这些特定排列的数量。例如 N = 5 N=5 N=5 K = 3 K=3 K=3的时候,满足条件的排列有 15 15 15个,它们是:

  • [ 1 , 2 , 5 , 4 , 3 ] [1, 2, 5, 4, 3] [1,2,5,4,3]
  • [ 1 , 3 , 4 , 5 , 2 ] [1, 3, 4, 5, 2] [1,3,4,5,2]
  • [ 1 , 3 , 5 , 2 , 4 ] [1, 3, 5, 2, 4] [1,3,5,2,4]
  • [ 1 , 4 , 2 , 5 , 3 ] [1, 4, 2, 5, 3] [1,4,2,5,3]
  • [ 1 , 4 , 3 , 2 , 5 ] [1, 4, 3, 2, 5] [1,4,3,2,5]
  • [ 1 , 5 , 2 , 3 , 4 ] [1, 5, 2, 3, 4] [1,5,2,3,4]
  • [ 2 , 1 , 4 , 5 , 3 ] [2, 1, 4, 5, 3] [2,1,4,5,3]
  • [ 2 , 1 , 5 , 3 , 4 ] [2, 1, 5, 3, 4] [2,1,5,3,4]
  • [ 2 , 3 , 1 , 5 , 4 ] [2, 3, 1, 5, 4] [2,3,1,5,4]
  • [ 2 , 3 , 4 , 1 , 5 ] [2, 3, 4, 1, 5] [2,3,4,1,5]
  • [ 2 , 4 , 1 , 3 , 5 ] [2, 4, 1, 3, 5] [2,4,1,3,5]
  • [ 3 , 1 , 2 , 5 , 4 ] [3, 1, 2, 5, 4] [3,1,2,5,4]
  • [ 3 , 1 , 4 , 2 , 5 ] [3, 1, 4, 2, 5] [3,1,4,2,5]
  • [ 3 , 2 , 1 , 4 , 5 ] [3, 2, 1, 4, 5] [3,2,1,4,5]
  • [ 4 , 1 , 2 , 3 , 5 ] [4, 1, 2, 3, 5] [4,1,2,3,5]

输入格式:
输入共第一行,两个整数 N N N K K K

输出格式:
1 ⋯ N 1\cdots N 1N的逆序对数量为 K K K的特定排列的数量输出。为了避免高精度计算,请将结果对 10000 10000 10000取模后再输出。

数据范围:
对于全部数据,保证 N ≤ 100 N \le 100 N100 K ≤ N × ( N − 1 ) / 2 K \le N\times (N-1)/2 KN×(N1)/2

f [ n ] [ k ] f[n][k] f[n][k] 1 ∼ n 1\sim n 1n逆序对恰好有 k k k个的排列数量,其可以按照 n n n这个数字在什么位置来分类。如果 n n n在倒数第 i i i个位置,那么 n n n后面 i − 1 i-1 i1个数, n n n和它们形成了 i − 1 i-1 i1个逆序对,所以不含 n n n的逆序对个数应该是 k − i + 1 k-i+1 ki+1个。所以: f [ n ] [ k ] = ∑ i = 1 n f [ n − 1 ] [ k − i + 1 ] = ∑ i = 0 n − 1 f [ n − 1 ] [ k − i ] f[n][k]=\sum_{i=1}^{n} f[n-1][k-i+1]=\sum_{i=0}^{n-1} f[n-1][k-i] f[n][k]=i=1nf[n1][ki+1]=i=0n1f[n1][ki]其中 f [ 0 ] [ 0 ] = 1 f[0][0]=1 f[0][0]=1。代码如下:

#include <iostream>
using namespace std;

const int N = 5010, MOD = 10000;
int f[N][N];
int n, k;

int main() {
  scanf("%d%d", &n, &k);
  f[0][0] = 1;
  for (int i = 1; i <= n; i++)
    for (int j = 0; j <= k; j++)
      for (int l = 0; l <= min(j, i - 1); l++)
        f[i][j] = (f[i][j] + f[i - 1][j - l]) % MOD;

  printf("%d\n", f[n][k]);
}

时间复杂度 O ( n 2 k ) O(n^2k) O(n2k),空间 O ( n k ) O(nk) O(nk)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值