LGV定理相关
Posted chaoswr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LGV定理相关相关的知识,希望对你有一定的参考价值。
又是一个看起来神奇无比的东东,证明是不可能证明的,这辈子不可能看懂的,知道怎么用就行了,具体看wikihttps://en.wikipedia.org/wiki/Lindstr%C3%B6m%E2%80%93Gessel%E2%80%93Viennot_lemma
LGV定理就是求n个起点到n个终点(且一个起点对应一个终点)的不相交路径数目的一种方法,光看这句话不好理解,来看一道cf题
这道题给你一个n*m的矩阵(1~n, 1~m),现在有两只乌龟都从左上角(1,1)出发,到达右下角(n,m),乌龟每次只能往右或者往下走一格,且两只乌龟走的路径不能交叉,问一共有多少种走法。首先显然可知的是一只乌龟必然从(1,2)走到(n-1, m),另一只必然从(2,1)走到(n,m-1),这个画画图就知道很显然了,那么我们可以看作有两个2个起点,2个终点,问共多少种不相交路径,这就是LGV定理了。
LGV定理实际上是求一个行列式
ai是起点,bi是终点,e(ai, bj)代表从ai为起点到bj为终点的方法数目,特别的注意ai对应bi(就是我们想求的起点到终点的方案数)
那么对于这道题,就相当于求一个2x2行列式的值。
|e1, e2|
|e3, e4|
其中
e1 = a1(2,1)-->b1(n,m-1) 的方案数
e2 = a1(2,1)-->b2(n-1,m) 的方案数
这两个用一遍dp求出来
e3 = a2(1,2)-->b1n,m-1) 的方案数
e4 = a2(1,2)-->b2(n-1,m) 的方案数
这两个也用一遍dp求出来
然后只要代入行列式,就能求得a1-b1,a2-b2且路径不相交的方法数ans=(e1*e4-e2*e3)了
#include <iostream> #include <string.h> #include <cstdio> #include <vector> #include <queue> #include <stack> #include <math.h> #include <string> #include <algorithm> #include <functional> #define SIGMA_SIZE 26 #define lson rt<<1 #define rson rt<<1|1 #define lowbit(x) (x&-x) #define foe(i, a, b) for(int i=a; i<=b; i++) #define fo(i, a, b) for(int i=a; i<b; i++) #define pii pair<int,int> #pragma warning ( disable : 4996 ) using namespace std; typedef long long LL; inline LL LMax(LL a, LL b) { return a>b ? a : b; } inline LL LMin(LL a, LL b) { return a>b ? b : a; } inline LL lgcd(LL a, LL b) { return b == 0 ? a : lgcd(b, a%b); } inline LL llcm(LL a, LL b) { return a / lgcd(a, b)*b; } //a*b = gcd*lcm inline int Max(int a, int b) { return a>b ? a : b; } inline int Min(int a, int b) { return a>b ? b : a; } inline int gcd(int a, int b) { return b == 0 ? a : gcd(b, a%b); } inline int lcm(int a, int b) { return a / gcd(a, b)*b; } //a*b = gcd*lcm const LL INF = 0x3f3f3f3f3f3f3f3f; const LL mod = 1e9+7; const double eps = 1e-8; const int inf = 0x3f3f3f3f; const int maxk = 3e6 + 5; const int maxn = 7e7 + 5; bool g[3010][3010]; int row, col; char str[3010]; LL dp[3010][3010]; void init() { cin >> row >> col; for (int i = 1; i <= row; i++ ) { scanf("%s", str+1); for ( int j = 1; j <= col; j++ ) { if (str[j]==‘#‘) g[i][j] = true; } } } pair<LL, LL> getRoad(int x, int y) { memset(dp, 0, sizeof(dp)); dp[1][1] = 1; for (int i = x; i <= row; i++) { for (int j = y; j <= col; j++) { if (!g[i][j]) dp[i][j] = (dp[i][j]+dp[i-1][j]+dp[i][j-1])%mod; } } return make_pair(dp[row][col-1], dp[row-1][col]); } int main() { init(); LL x1, x2, x3, x4; pair<LL, LL> tmp; tmp = getRoad(2, 1); x1 = tmp.first; x2 = tmp.second; tmp = getRoad(1, 2); x3 = tmp.first; x4 = tmp.second; LL ans = ((x1*x4)%mod-(x2*x3)%mod+mod)%mod; printf("%lld ", ans); return 0; }
以上是关于LGV定理相关的主要内容,如果未能解决你的问题,请参考以下文章