[BZOJ2431] [HAOI2009]逆序对数列
Description
对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数。若对于任意一个由1~n自然数组成的
数列,可以很容易求出有多少个逆序对数。那么逆序对数为k的这样自然数数列到底有多少个?
Input
第一行为两个整数n,k。
Output
写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果。
Sample Input
4 1
Sample Output
3
样例说明:
下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;
100%的数据 n<=1000,k<=1000
样例说明:
下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;
100%的数据 n<=1000,k<=1000
本蒟蒻能写出来的题已经不多了...
这题也是其中的一个...
容易想到,一个序列,在其后面加一个数,产生的逆序对数量是前面大于它的数的个数。
那么我们设$\large f[i][j]$,为填到了第i位,有j个逆序对的方案数。
因为要求答案是n的一个排列, 所以我们不妨假设前i个数正好是一个i+1排列中的i个,那么我们加入一个数k,会产生$i+1-k$个逆序对。
然后就这样递推。
不知为何$\large O(N^3)$过了。
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; #define reg register #define mod 10000 int n, K; int f[1005][1005]; int main() { scanf("%d%d", &n, &K); f[0][0] = 1; for (reg int i = 0 ; i < n ; i ++) for (reg int j = 0 ; j <= K ; j ++) for (reg int k = 1 ; k <= i + 1 ; k ++) { if(j+i+1-k<=K)(f[i+1][j+(i+1-k)] += f[i][j]) %= mod; } cout << f[n][K] << endl; return 0; }