Codeforces Round #215 (Div. 1)E. Sereja and Intervals【DP】

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

 

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值