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;
}
};