思路:
*
* 用dp[i][l][r]表示到前i个数为止, 有l个左边界和r个右边界的可能种数
* 那么第i个数可能是左边界, 右边界, 既是左边界又是右边界, 不是边界这几种可能
* 此时有
* dp[i][l][r] = dp[i - 1][l][r] + dp[i - 1][l - 1][r] + dp[i - 1][l][r - 1] + dp[i - 1][l - 1][r - 1]
* 注意4种转移的条件
* 当i == x时, 可能是左边界, 既是左边界又是右边界
* 此时dp[x][l][r] = dp[i - 1][l - 1][r] + dp[i - 1][l - 1][r - 1]
* 初始化dp[0][0][0] = 1, 对于i个数可以滚动数组减少内存消耗
*
代码:
#include <bits/stdc++.h>
using namespace std;
const long long mod = 1e9 + 7;
int n, m, x;
long long dp[2][325][325];
void add(long long &a, long long b) {
a += b;
if (a >= mod) a -= mod;
return;
}
void solve() {
dp[0][0][0] = 1;
int kkk = 1, i, l, r;
for (i = 1; i <= m; i++, kkk ^= 1) {
for (l = 0; l <= n; l++)
for (r = 0, dp[kkk][l][0] = 0; r <= l; r++, dp[kkk][l][r] = 0) {
if (i == x) {
if (l) add(dp[kkk][l][r], dp[kkk ^ 1][l - 1][r]);
if (l && r) add(dp[kkk][l][r], dp[kkk ^ 1][l - 1][r - 1]);
} else {
add(dp[kkk][l][r], dp[kkk ^ 1][l][r]);
if (l - 1 >= r) add(dp[kkk][l][r], dp[kkk ^ 1][l - 1][r]);
if (r) add(dp[kkk][l][r], dp[kkk ^ 1][l][r - 1]);
if (l && r) add(dp[kkk][l][r], dp[kkk ^ 1][l - 1][r - 1]);
}
}
}
long long ans = dp[kkk ^ 1][n][n];
for (int i = 1; i <= n; i++) ans = (ans * i) % mod;
cout << ans << endl;
}
int main() {
ios :: sync_with_stdio(false);
cin >> n >> m >> x;
if (n > m) cout << 0 << endl;
else solve();
return 0;
}