BZOJ2431 HAOI2009 逆序對數列

2022-05-08 07:21:13 字數 1491 閱讀 2653

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

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

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

樣例輸入

4 1樣例輸出

3樣例說明:

下列3個數列逆序對數都為1;分別是1 2 4 3 ;1 3 2 4 ;2 1 3 4;

測試資料範圍

30%的資料 n<=12

100%的資料 n<=1000,k<=1000

正解:dp(遞推)

解題報告:

這道題我居然沒能一眼秒。。。

令f[i][j]表示前i個數逆序對數為j的序列個數,考慮dp(遞推)。因為插入前i-1個數的時候方案已經得出了,我們需要插入第i個數獲得新的一些序列。

因為i比前面任何乙個數都要大,所以插在第幾位,就會比後面的數大,對於總逆序對產生貢獻。考慮貢獻大小,可以插在前i-1個數的最後面,那麼對於逆序對數沒有產生任何貢獻,所以就是從f[i-1][j]轉移過來,但是插在其他位置呢?如果插在i-2個數後面就是產生1的貢獻,所以是f[i-1][j-1]。。。最後i-1中總共i-1個數,所以新產生的貢獻最大為i-1。可以得到方程式:f[i][j]=∑f[i-1][j-k](0<=k

複雜度o(n^3)但是可以優化。因為每次用的是一段,所以字首和優化一下,沒必要每次重新統計。

1

//it is made by jump~

2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 #include 10 #include 11 #include 12 #include

13#ifdef win32

14#define ot "%i64d"

15#else

16#define ot "%lld"

17#endif

18using

namespace

std;

19 typedef long

long

ll;20

const

int maxn = 1011;21

const

int mod = 10000;22

intn,k;

23int f[maxn][maxn];//

f[i][j]表示前i個數逆序對為j個的序列數

2425 inline int

getint()

2634

35 inline void

work()47}

48 printf("%d"

,f[n][k]);49}

5051

intmain()

52

bzoj2431 HAOI2009 逆序對數列

對於乙個數列,如果有ii aj,那麼我們稱ai與aj為一對逆序對數。若對於任意乙個由1 n自然數組成的數列,可以很容易求出有多少個逆序對數。那麼逆序對數為k的這樣自然數數列到底有多少個?第一行為兩個整數n,k。寫入乙個整數,表示符合條件的數列個數,由於這個數可能很大,你只需輸出該數對10000求餘數...

bzoj2431 HAOI2009 逆序對數列

天哪天哪天哪 我們用f i j 來表示前i個數,有j對逆序對的方案數,so考慮插入,因為i比1到i 1裡面的任何乙個數都要大,所以插入的時候後面有多少個數,就會多出多少逆序對,所以前面的符合條件的都可以轉移,f i j sigma f i 1 j k k屬於0到i 1,然而字首和神煩.include...

bzoj2431 HAOI2009 逆序對數列

dp 令b i j 表示n i,k j時的答案 則b 1 0 1 b 2 0 1 b 2 1 1 b 3 0 1 b 3 1 2 b 3 2 2 b 3 3 1 我們觀察發現 至少我是觀察 b i j b i 1 j i 1 b i 1 j 注意j i 1 0時令其為0 j i 1 i 2 2,即j...