6.28 不等序列
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 不等序列