E. Sereja and Intervals
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output
Sereja is interested in intervals of numbers, so he has prepared a problem about intervals for you. An interval of numbers is a pair of integers [l, r] (1 ≤ l ≤ r ≤ m). Interval [l1, r1] belongs to interval [l2, r2] if the following condition is met: l2 ≤ l1 ≤ r1 ≤ r2.
Sereja wants to write out a sequence of n intervals [l1, r1], [l2, r2], ..., [ln, rn] on a piece of paper. At that, no interval in the sequence can belong to some other interval of the sequence. Also, Sereja loves number x very much and he wants some (at least one) interval in the sequence to have li = x. Sereja wonders, how many distinct ways to write such intervals are there?
Help Sereja and find the required number of ways modulo 1000000007 (109 + 7).
Two ways are considered distinct if there is such j (1 ≤ j ≤ n), that the j-th intervals in two corresponding sequences are not equal.
Input
The first line contains integers n, m, x (1 ≤ n·m ≤ 100000, 1 ≤ x ≤ m) — the number of segments in the sequence, the constraints on the numbers in segments and Sereja's favourite number.
Output
In a single line print the answer modulo 1000000007 (109 + 7).
Examples
input
Copy
1 1 1
output
Copy
1
input
Copy
3 5 1
output
Copy
240
input
Copy
2 3 3
output
Copy
6
Note
In third example next sequences will be correct: {[1, 1], [3, 3]}, {[1, 2], [3, 3]}, {[2, 2], [3, 3]}, {[3, 3], [1, 1]}, {[3, 3], [2, 2]}, {[3, 3], [1, 2]}.
分析:起初把题读错了,以为每个区间都要相互没有重叠,于是推了一个公式出来才发现。。。
考虑一下区间是怎么包含的,当我们把这些区间看成若干个左括号与右括号,那么要如何才能让这些括号匹配之后相互不包含呢?只需要第一个左括号与第一个右括号匹配,第二个和第二个匹配,如果不存在多个左括号或者右括号在同一个点上的,这种匹配方法是唯一解。那么现在问题就转化成了放括号的问题。
那么现在每个点上的情况无非只有4种
(1)什么都不放
(2)只放左括号
(3)只放右括号
(4)一左一右
且必须满足每个前缀中右括号的数量要小于等于左括号的数量。
于是就变成了一个很sb的DP了。注意当i==x的时候是必须放左括号的。
并且n*m<=1e5,如果n>m的话很明显答案是0,而n<m的话,n最大只有300多,那么可以用DP[i][j][k]表示前i个点放j个左括号和k个右括号的方案数,最后dp[m][n][n]*n!就是答案。再滚动数组优化一下就OK了。
#include "bits/stdc++.h"
namespace fastIO {
#define BUF_SIZE 100000
bool IOerror = 0;
inline char nc() { static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;if (p1 == pend) { p1 = buf;pend = buf + fread(buf, 1, BUF_SIZE, stdin);if (pend == p1) { IOerror = 1;return -1; }}return *p1++;}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
inline void read(int &x) { char ch;while (blank(ch = nc()));if (IOerror) return;for (x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0'); }
inline void Out(long long a) { if (a < 0) { putchar('-');a = -a; }if (a >= 10) { Out(a / 10); }putchar(a % 10 + '0'); }
#undef BUF_SIZE
};
using namespace fastIO;
using namespace std;
const int mod = 1e9+7;
long long dp[2][400][400];
int main() {
int n,m,x;
cin>>n>>m>>x;
if(n>m){puts("0");return 0;}
dp[0][0][0]=1;
for (int i = 1; i <= m; ++i) {
int cnt = i&1;
for (int j = 0; j <= n; ++j) {
for (int k = 0; k <= j; ++k) {
dp[cnt][j][k]=0;
if(j>=1)dp[cnt][j][k]=(dp[cnt][j][k] + dp[cnt^1][j-1][k])%mod;
if(j>=1&&k>=1)dp[cnt][j][k]=(dp[cnt][j][k] + dp[cnt^1][j-1][k-1])%mod;
if(i!=x){
dp[cnt][j][k] = (dp[cnt][j][k] + dp[cnt^1][j][k])%mod;
if(k>=1)dp[cnt][j][k] = (dp[cnt][j][k] + dp[cnt^1][j][k-1])%mod;
}
}
}
}
long long ans = dp[m&1][n][n];
for (int i = 2; i <= n; ++i) {
ans = ans * i %mod;
}
cout<<ans<<endl;
}