CodeForces - 367E:Sereja and Intervals(組合數&&DP)
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
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
Help Sereja and find the required number of ways modulo 1000000007 (109 + 7).
Two ways are considered distinct if there is such j
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.
OutputIn a single line print the answer modulo 1000000007 (109 + 7).
Examples Input1 1 1Output
1Input
3 5 1Output
240Input
2 3 3Output
6Note
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)