2016MUTC9 HDU5852 Intersection is not allowed!

题目大意

给定一个$n\times n$的棋盘,从求从最上一行的$k$个点出发,每次只能往下或往左走不相交地走到最下面一行$k$个点的方案数。

简要题解

建立一个$k\times 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 == '\n' || ret == '\r' || 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 }

 

转载于:https://www.cnblogs.com/ichn/p/6410178.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值