CodeForces 367E Sereja and Intervals

CodeForces 3 67E

 

Description

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).

 

 

 

Input
1 1 1

 

Output
1
Input
3 5 1
Output
240
Input
2 3 3
Output
6

 

 题意:给出一个区间,在这个区间内选n个L和R值,使得这n个L,R不能存在包含关系,问一共有多少种方法。

 

sl:  可以这么搞,设当前区间的长度为L,左节点有a个,右节点有b个,dp[L][a][b] 代表解的个数。

有4种转移。

dp[k][i+1][j]+=dp[k-1][i][j]; 以第k个节点为左节点。

dp[k][i+1][j+1] 以第k个节点为左节点也为右节点。

 

当当前位置处于x时不能将当前节点发给右节点,因为已经和上面的重复。

另外可以用滚动数组降去k那一维。 

最后乘上n的全排列,对应数对的顺序。 

 

 ps:感觉这道题目好精妙的感觉。

 

 1 #include<cstring>
 2 #include<cstdio>
 3 #include<algorithm>
 4  using  namespace std;
 5 typedef  long  long LL;
 6  const  int MOD = 1e9+ 7;
 7  const  int MAX =  500;
 8  int dp[ 2][MAX][MAX];
 9  int main()
10 {
11      int n,m,x,next;
12      while(scanf( " %d %d %d ",&n,&m,&x)== 3)
13     {
14         memset(dp, 0, sizeof(dp));
15         dp[ 0][ 0][ 0]= 1;
16         next= 0;
17          if(n>m) printf( " 0\n ");
18          else
19         {
20              for( int k= 1;k<=m;k++)
21             {
22                 next=next^ 1;
23                  for( int i= 0;i<=n;i++)  for( int j= 0;j<=n;j++)
24                 dp[next][i][j]= 0;
25                  for( int i= 0;i<=n;i++)  for( int j= 0;j<=i;j++)
26                 {
27                     dp[next][i+ 1][j]=(dp[next][i+ 1][j]+dp[next^ 1][i][j])%MOD;
28                     dp[next][i+ 1][j+ 1]=(dp[next][i+ 1][j+ 1]+dp[next^ 1][i][j])%MOD;
29                      if(k!=x)
30                     {
31                         dp[next][i][j+ 1]=(dp[next][i][j+ 1]+dp[next^ 1][i][j])%MOD;
32                         dp[next][i][j]=(dp[next][i][j]+dp[next^ 1][i][j])%MOD;
33                     }
34                 }
35             }
36             LL ans=dp[next][n][n]%MOD;
37              for( int i= 1;i<=n;i++) ans=(ans*i)%MOD;
38             printf( " %I64d\n ",ans);
39         }
40     }
41      return  0;

42 } 

 

 

 

 


转载于:https://www.cnblogs.com/acvc/p/3653209.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值