题目大意
给定一个$n imes n$的棋盘,从求从最上一行的$k$个点出发,每次只能往下或往左走不相交地走到最下面一行$k$个点的方案数。
简要题解
建立一个$k imes k$的矩阵$D$,其中$D_{ij}$表示从$a_i$到$b_j$的方案数,由Lindström–Gessel–Viennot lemma,答案即为$Det(D)$。
1 #include <bits/stdc++.h> 2 using namespace std; 3 namespace my_header { 4 #define pb push_back 5 #define mp make_pair 6 #define pir pair<int, int> 7 #define vec vector<int> 8 #define pc putchar 9 #define clr(t) memset(t, 0, sizeof t) 10 #define pse(t, v) memset(t, v, sizeof t) 11 #define bl puts("") 12 #define wn(x) wr(x), bl 13 #define ws(x) wr(x), pc(' ') 14 const int INF = 0x3f3f3f3f; 15 typedef long long LL; 16 typedef double DB; 17 inline char gchar() { 18 char ret = getchar(); 19 for(; (ret == ' ' || ret == ' ' || ret == ' ') && ret != EOF; ret = getchar()); 20 return ret; } 21 template<class T> inline void fr(T &ret, char c = ' ', int flg = 1) { 22 for(c = getchar(); (c < '0' || '9' < c) && c != '-'; c = getchar()); 23 if (c == '-') { flg = -1; c = getchar(); } 24 for(ret = 0; '0' <= c && c <= '9'; c = getchar()) 25 ret = ret * 10 + c - '0'; 26 ret = ret * flg; } 27 inline int fr() { int t; fr(t); return t; } 28 template<class T> inline void fr(T&a, T&b) { fr(a), fr(b); } 29 template<class T> inline void fr(T&a, T&b, T&c) { fr(a), fr(b), fr(c); } 30 template<class T> inline char wr(T a, int b = 10, bool p = 1) { 31 return a < 0 ? pc('-'), wr(-a, b, 0) : (a == 0 ? (p ? pc('0') : p) : 32 (wr(a/b, b, 0), pc('0' + a % b))); 33 } 34 template<class T> inline void wt(T a) { wn(a); } 35 template<class T> inline void wt(T a, T b) { ws(a), wn(b); } 36 template<class T> inline void wt(T a, T b, T c) { ws(a), ws(b), wn(c); } 37 template<class T> inline void wt(T a, T b, T c, T d) { ws(a), ws(b), ws(c), wn(d); } 38 template<class T> inline T gcd(T a, T b) { 39 return b == 0 ? a : gcd(b, a % b); } 40 template<class T> inline T fpw(T b, T i, T _m, T r = 1) { 41 for(; i; i >>= 1, b = b * b % _m) 42 if(i & 1) r = r * b % _m; 43 return r; } 44 }; 45 using namespace my_header; 46 47 const int MOD = 1e9 + 7; 48 const int MAXN = 2e5 + 100; 49 const int MAXK = 100 + 10; 50 51 int fac[MAXN], rfac[MAXN], rev[MAXN]; 52 53 void init() { 54 fac[0] = 1; 55 for (int i = 1; i < MAXN; ++i) 56 fac[i] = 1LL * fac[i - 1] * i % MOD; 57 rfac[MAXN - 1] = fpw((LL)fac[MAXN - 1], (LL)MOD - 2, (LL)MOD); 58 for (int i = MAXN - 2; 0 <= i; --i) 59 rfac[i] = 1LL * rfac[i + 1] * (i + 1) % MOD; 60 for (int i = 1; i < MAXN; ++i) 61 rev[i] = 1LL * fac[i - 1] * rfac[i] % MOD; 62 } 63 64 int c(int n, int m) { 65 if (n < m) 66 return 0; 67 return 1LL * fac[n] * rfac[m] % MOD * rfac[n - m] % MOD; 68 } 69 70 int det(int (*d)[MAXK], int n) { 71 int ans = 1, s = 1; 72 for (int i = 1; i <= n; ++i) { 73 for (int j = i + 1; j <= n; ++j) { 74 int x = i, y = j; 75 while (d[y][i]) { 76 int t = d[x][i] / d[y][i]; 77 for (int k = i; k <= n; ++k) 78 d[x][k] = (d[x][k] - 1LL * d[y][k]* t % MOD + MOD) % MOD; 79 swap(x, y); 80 } 81 if (x != i) { 82 for (int k = i; k <= n; ++k) 83 swap(d[x][k], d[y][k]); 84 s *= -1; 85 } 86 } 87 if (d[i][i] == 0) 88 return 0; 89 ans = 1LL * ans * d[i][i] % MOD; 90 } 91 return (ans * s % MOD + MOD) % MOD; 92 } 93 94 int n, k, a[MAXK], b[MAXK], d[MAXK][MAXK]; 95 96 int getNum(int u, int v) { 97 return c(n + v - u - 1, n - 1); 98 } 99 100 int main() { 101 #ifdef lol 102 freopen("h.in", "r", stdin); 103 freopen("h.out", "w", stdout); 104 #endif 105 init(); 106 int T = fr(); 107 while (T--) { 108 fr(n, k); 109 for (int i = 1; i <= k; ++i) 110 fr(a[i]); 111 for (int i = 1; i <= k; ++i) 112 fr(b[i]); 113 for (int i = 1; i <= k; ++i) 114 for (int j = 1; j <= k; ++j) 115 d[i][j] = getNum(a[i], b[j]); 116 wt(det(d, k)); 117 } 118 119 return 0; 120 }