问题描述: 度度熊最近对全排列特别感兴趣,对于1到n的一个排列,度度熊发现可以在中间根据大小关系插入合适的大于和小于符号(即 ‘>’ 和 ‘<’ )使其成为一个合法的不等式数列。但是现在度度熊手中只有k个小于符号(即’<’)和n-k-1个大于符号(即’>’),度度熊想知道对于1至n任意的排列中有多少个排列可以使用这些符号使其为合法的不等式数列。
输入描述:
输入包括一行,包含两个整数n和k(k < n ≤ 1000)
输出描述:
输出满足条件的排列数,答案对2017取模。
输入例子:
5 2
输出例子:
66
Dynamic Programming
dp[i][j]
denotes the number of permutations satisfied the condition where there are i numbers and j less-than-signs. When the (i+1)-th number is interpolated, there are four cases:
1) Inserted before the head of permutation. e.g.
x−→−−−−−before head(a<b)⇒(x>a<b)
. A greater-than-sign is generated.
2) Inserted after the tail of permutation. e.g.
x−→−−−−after tail(a<b)⇒(a<b<x)
. A less-than-sign is generated.
3) Inserted in the middle of a greater-than-sign. e.g
x−→−−−−−−−−−−greater−than−sign(a>b)⇒(a<x>b)
. A less-than-sign is generated.
4) Inserted in the middle of a less-than-sign. e.g
x−→−−−−−−−−less−than−sign(a<b)⇒(a<x>b)
. A greater-than-sign is generated.
Hence, dp[i][j] equals to sum of the four cases below:
- dp[i−1][j] : i-th number is serted before the head. No less-than-sign is producted, so there’re j less-than-signs in this case.
- dp[i−1][j−1] : i-th number is serted after the tail. a less-than-sign is generated after inserting a number.
- dp[i−1][j−1]∗(i−j−1) : a less-than-sign is produced when the i-th number inserted in the middle of a greater-than-sign, (i−j−1) choices in total.
-
dp[i−1][j]∗j
: inserted inner a less-than-sign,
j
choices in total.
Namely,dp[i][j]=dp[i−1][j−1]∗(i−j)+dp[i−1][j]∗(j+1)
Modulo Equivalencies
- (a+b) mod n=[(a mod n)+(b mod n)] mod n
- ab mod n=[(a mod n)(b mod n)] mod n
Code in Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int[][] dp = new int[n+1][k+1];
for (int i = 1; i < n+1; i++)
dp[i][0] = 1; //all of the other values are initialized as 0.
for (int i = 2; i < n+1; i++) {
for (int j = 1; j <= k && j < i; j++) {
dp[i][j] = (dp[i-1][j-1]*(i-j)+dp[i-1][j]*(j+1))%2017;
}
}
System.out.println(dp[n][k]);
}
}