1. 程式人生 > >CodeForces - 367E:Sereja and Intervals(組合數&&DP)

CodeForces - 367E:Sereja and Intervals(組合數&&DP)

ant lov strong clas require sequence 組合 pri c++

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: l

2 ≤ 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
1 1 1
Output
1
Input
3 5 1
Output
240
Input
2 3 3
Output
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]}.

題意:給定長度為M的數軸,讓你選擇N個帶編號的線段,使得沒有線段有包含關系。 給定X,讓你至少選擇了一個左端點為X的線段。

思路:N<=M; 所以N<sqrt(N*M)<=330; 沒有包含關系,那麽線段A的左端點大於B的左端點,那麽A的右端點也一定大於B的右端點。所以我們可以自己去匹配。只保存當點左端點和右端點個數即可。

用dp[i][j][x]表示前x個點選擇了i個左端點,j個右端點,不難得到方程。由於x可能有點大,我們用滾動數組。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=330;
const int Mod=1e9+7;
int dp[maxn][maxn][2];
int main()
{
    int N,M,X;
    scanf("%d%d%d",&N,&M,&X);
    if(N>M) return puts("0"),0;
    dp[0][0][0]=1;
    rep(k,1,M){//位置
      rep(i,0,min(N,M)){ //左括號
        rep(j,0,i){ //右括號
            int p=k&1;
            if(k==X){
                dp[i][j][p]=0;
                if(i>j) (dp[i][j][p]+=dp[i-1][j][p^1])%=Mod; //
                if(i&&j) (dp[i][j][p]+=dp[i-1][j-1][p^1])%=Mod;//左+右
            }
            else {
                dp[i][j][p]=dp[i][j][p^1]; //不放
                if(i>j) (dp[i][j][p]+=dp[i-1][j][p^1])%=Mod; //
                if(i&&j) (dp[i][j][p]+=dp[i-1][j-1][p^1])%=Mod;//左+右
                if(j) (dp[i][j][p]+=dp[i][j-1][p^1])%=Mod;//
            }
        }
      }
    }
    rep(i,1,N) dp[N][N][M&1]=1LL*dp[N][N][M&1]*i%Mod;
    printf("%d\n",dp[N][N][M&1]);
    return 0;
}

CodeForces - 367E:Sereja and Intervals(組合數&&DP)