1. 程式人生 > >6.28 不等序列

6.28 不等序列

數字 getch 輸出 num 整數 for family 轉移 6.2

Problem 2 不等數列(num.cpp/c/pas)

【題目描述】

1到n任意排列,然後在排列的每兩個數之間根據他們的大小關系插入“>”和“<”。問在所有排列中,有多少個排列恰好有k個“<”。答案對2012取模。

【輸入格式】

第一行2個整數n,k。

【輸出格式】

一個整數表示答案。

【樣例輸入】

5 2

【樣例輸出】

66

【數據範圍】

對於30%的數據:n <= 10

對於100%的數據:k<n<=1000,

乍一看,好像是動態規劃,仔細看,還真是動態規劃(以上為本人賣萌)

說正經題解:

因為此題只需要得出數字之間的大小關系,而並不需要得出具體的數字之間的差值,所以可以看為從小到大向一個數列中插入數字,這樣就是只需要記錄第幾個數字被插入就可以了,同時記錄插入到這時的

“<”的數量。

使用一個二維數組記錄,分別記錄插入的數字與已有的“<”個數,於是轉移方程就出來了:

f[i][j]=(f[i-1][j-1]*(i-j))+(f[i-1][j]*(j+1))

這由兩種情況組成:

插入“<”連接的兩個數字之中,由於是從大到小插入,所以小於號數量並沒有改變

如果插入">"連接的兩個數字中,小於號會增加一個。

最後f[n][k]就是答案

另附代碼:

#include <cstdio>

int n,k,i,j;

int f[1003][1003];

int read()

{

  int y=0;char x=getchar();

  while(x>=‘0‘&&x<=‘9‘)

  {

  y=y*10+x-‘0‘;

  x=getchar();

  }

  return y;

}

int main()

{

n=read();k=read();

for(i=1;i<=n;i++) f[i][0]=1;

f[2][1]=1;

for(i=3;i<=n;i++)

{

for(j=1;j<i;j++)

{

f[i][j]=(f[i-1][j-1]*(i-j))%2015+(f[i-1][j]*(j+1))%2015;

}

}

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

return 0;

}

6.28 不等序列