Problem Statement |
|||||||||||||
You are given an int N and a int[] pos. We are interested in some permutations of the set {1,2,...,N}. A permutation p is called good if the following condition is satisfied: for each valid k, we have p(k) < p(k+1) if and only if k is an element of pos. Return the number of good permutations, modulo 1,000,000,007. |
|||||||||||||
Definition |
|||||||||||||
|
|||||||||||||
Constraints |
|||||||||||||
- | N will be between 1 and 200, inclusive. | ||||||||||||
- | pos will contain between 1 and N-1 elements, inclusive. | ||||||||||||
- | Elements of pos will be distinct. | ||||||||||||
- | Each element of pos will be between 1 and N-1, inclusive. | ||||||||||||
Examples |
|||||||||||||
0) | |||||||||||||
|
|||||||||||||
1) | |||||||||||||
|
|||||||||||||
2) | |||||||||||||
|
|||||||||||||
3) | |||||||||||||
|
|||||||||||||
4) | |||||||||||||
|
题目如上,也就是要求带有约束的permutation有多少种,有约束的时候p(k)<p(k+1),没有约束的时候p(k)>p(k+1), 鉴于topcoder里出题人写的代码中的注释有误,导致别人非常难理解,故在这里来把问题讲清楚一下。
我们用dp[i][j]表示处理前i个数,并以第j小的那个数最为第i个数时的方案总数,如果有约束的话,即第i-1个数要比第i个数小的话,那么dp[i][j] = sum(dp[i-1][k])(k<j),也就是前i-1个数中要取第k小的数作为第i-1个,这样才能保证p(i-1)<p(i),没有约束的话,即第i-1个数要比第i个数大的话,那么dp[i][j] = sum(dp[i-1][k])(k>=j),这里为什么k>=j而不是k>j,因为在i个数里面取出第j小的数x之后,前面i-1个数中第j小的数还是比 x要大的(原本排第j+1小的,因为第j小被取出了,故在前i-1个中排第j小了)初始化dp[1][1]表示一共1个数,以第1小的数作为结尾,那么当然只有一种方案。
所以代码如下:
#include <vector> #include <list> #include <map> #include <set> #include <queue> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <string.h> using namespace std; bool g[10000]; int dp[220][220]; class PermutationCountsDiv2 { public: int countPermutations(int N, vector <int> pos) { int mod = 1000000007; memset(g, 0, sizeof(g)); for (int x : pos) g[x] = true; memset(dp, 0, sizeof(dp)); dp[1][1] = 1; for (int i = 2; i <= N; i++) { for (int last = 1; last <= i; last++) { if (!g[i - 1]) { for (int j = last; j <= i; j++) dp[i][last] = (dp[i][last] + dp[i - 1][j]) % mod; } else { for (int j = last - 1; j >= 1; j--) dp[i][last] = (dp[i][last] + dp[i - 1][j]) % mod; } } } int res = 0; for (int i = 0; i <= N; i++) res = (res + dp[N][i]) % mod; return res; } };
原文:http://blog.csdn.net/wangyuquanliuli/article/details/45175243