1. 程式人生 > >【bzoj2431】[HAOI2009]逆序對數列 dp

【bzoj2431】[HAOI2009]逆序對數列 dp

sum 什麽 clu 優化 col 自然數 amp 如果 bzoj

題目描述

對於一個數列{ai},如果有i<j且ai>aj,那麽我們稱ai與aj為一對逆序對數。若對於任意一個由1~n自然數組成的 數列,可以很容易求出有多少個逆序對數。那麽逆序對數為k的這樣自然數數列到底有多少個?

輸入

第一行為兩個整數n,k。

輸出

寫入一個整數,表示符合條件的數列個數,由於這個數可能很大,你只需輸出該數對10000求余數後的結果。

樣例輸入

4 1

樣例輸出

3


題解

dp傻*題

設f[i][j]表示1~i組成逆序對個數為j的數列的方案數,那麽考慮第i個元素,它對逆序對個數可能產生0~i-1的貢獻。

所以有f[i][j]=∑f[i-1][j-k],0≤k<i。

然後用一個前綴和來優化即可。註意點邊界什麽的就行。

#include <cstdio> 
#include <algorithm> 
#define mod 10000 
using namespace std; 
int f[1010][1010] , sum[1010][1010]; 
int main() 
{ 
    int n , k , i , j; 
    scanf("%d%d" , &n , &k); 
    f[0][1] = sum[0][1] = 1; 
    for(i = 1 ; i <= n ; i ++ ) 
    { 
        for(j = 1 ; j <= k + 1 && j <= i * (i - 1) / 2 + 1 ; j ++ ) f[i][j] = (sum[i - 1][j] - sum[i - 1][max(0 , j - i)] + mod) % mod; 
        for(j = 1 ; j <= k + 1 ; j ++ ) sum[i][j] = (sum[i][j - 1] + f[i][j]) % mod; 
    } 
    printf("%d\n" , f[n][k + 1]); 
    return 0; 
}

【bzoj2431】[HAOI2009]逆序對數列 dp