dp - 逆序数序列

对于一个数列{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
 
题意:让你求长度为 N 的序列逆序数为K的有多少种情况
思路分析:考虑在增加一位,第 i 位时,就相当于在长度为i-1的序列全排列中插入以个 i ,由于插入的 i 值是最大的,因此其可以增加的逆序数数量为 0~i-1 ,当将 i 插入到最末尾时,不会增加任何逆序数,当插入到倒数第二位时,会增加一位逆序数,就这样推一下就可以了。
定义 dp[i][j] 长度为 i 的序列逆序数为 j 的方案总数,在累加求和时要用前缀和优化一下
代码示例:
int dp[1005][1005];
int sum[1005];

int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    int n, k;
    
    cin >> n >> k;
    
    dp[0][0] = 0;
    for(int i = 1; i <= n; i++){
        dp[i][0] = 1;
        for(int j = 1; j <= k; j++){
            int s = max(0, j-i+1);
            int e = j;
            if (s == 0) dp[i][j] = sum[e];
            else dp[i][j] = (sum[e]+mod-sum[s-1])%mod;
        } 
        sum[0] = 1;
        for(int j = 1; j <= k; j++) {
            sum[j] = sum[j-1]+dp[i][j];
            sum[j] %= mod;
        }
    }
    printf("%d\n", dp[n][k]);
    return 0;
}

 

posted @ 2018-07-25 08:11  楼主好菜啊  阅读(354)  评论(0编辑  收藏  举报