有一个N行M列的棋盘,即该棋盘被分为N*M格。现在向棋盘中放棋子,每个格子中最多放一个棋子,也可以一个不放。放完棋子后需要满足如下要求:
1)对于第i行来说,其从左往右的前left[i] 个格子(即最左侧的left[i] 个连续的格子)中恰好一共有1个棋子;
2)对于第i行来说,其从右往左的前right[i]个格子(即最右侧的right[i]个连续的格子)中恰好一共有1个棋子;
3)对于每一列来说,这一列上的所有格子内含有的棋子数不得超过1个。
其中,1)与2)条件中,对所有 i 满足 left[i]+right[i] <= M,即两个区间不会相交。
问,符合上述条件情况下棋子的不同放法一共有多少种?输出放法的个数 mod 1,000,000,007后的结果。
例如样例中,只有如下图一种方法。
Input
第一行包含两个整数,N,M,其中1<=N<=50,2<=M<=200. 之后有N行,每行两个数left[i],right[i],其中,1<=left[i],right[i]<=M,且 left[i]+right[i] <= M。
Output
一个整数,即符合条件的方案数mod 1,000,000,007后的结果。
Input示例
2 4 1 2 2 1
Output示例
1
打死都想不出系列。
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> using namespace std; inline int read() { int res = 0;char ch=getchar(); while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48), ch=getchar(); return res; } #define reg register #define mod 1000000007 #define ll long long #define int long long int n, m; int L[205], R[205], Mid[205]; int f[205][205][55]; int fac[205], C[205][205]; inline int ksm(int x, int y) { int res = 1; while(y) { if (y & 1) res = (ll)(res * x) % mod; x = (ll)(x * x) % mod; y >>= 1; } return res; } ll ans; signed main() { n = read(), m = read(); for (reg int i = 1 ; i <= n ; i ++) { int l = read(), r = read(); L[l] ++, R[m+1-r]++; for (reg int j = l + 1 ; j <= m - r ; j ++) Mid[j]++; } fac[0] = 1; for (reg int i = 1 ; i <= 200 ; i ++) fac[i] = fac[i-1] * i % mod; C[0][0] = 1; for (reg int i = 1 ; i <= 200 ; i ++) { C[i][0] = 1; for (reg int j = 1 ; j <= i ; j ++) C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod; } f[0][0][0] = 1; for (reg int i = 0 ; i < m ; i ++) for (reg int j = 0 ; j <= i ; j ++) for (reg int k = 0 ; k <= n ; k ++) { if (j + 1 >= L[i+1]) (f[i+1][j+1-L[i+1]][k+R[i+1]] += (f[i][j][k] * (C[j+1][L[i+1]] * fac[L[i+1]]) % mod) % mod) %= mod; //空着不填或者填左端点 if (j >= L[i+1]) { (f[i+1][j-L[i+1]][k+R[i+1]] += (f[i][j][k] * (C[j][L[i+1]] * fac[L[i+1]] * Mid[i+1]) % mod) % mod) %= mod; //放在中间的空行 if (k + R[i+1]) (f[i+1][j-L[i+1]][k+R[i+1]-1] += (f[i][j][k] * (C[j][L[i+1]] * fac[L[i+1]] % mod * (k + R[i+1])) % mod) % mod) %= mod; } } for (reg int i = 0 ; i <= m ; i ++) ans = (ans + f[m][i][0]) % mod; printf("%lld ", ans); return 0; }