Lindström-Gessel-Viennot lemma Theorem determinant board

https://blog.csdn.net/qq_37025443/article/details/86537261  blog

 

Here is the explanation on the wiki, recommendations patiently read through ... although probably read or do not understand

https://en.wikipedia.org/wiki/Lindström–Gessel–Viennot_lemma

Lindström-Gessel-Viennot lemma is Theorem

Starting set A = (a1, a2, a3..an), it sets the end point B = (b1.b2, b3, .. bn)

P is assumed from a path from one point to another point, after the definition of w (P) = weight of the side product path

 

 

Definition of a n-tuple P '= (P1, P2, P3 ... PN)

Pi: -> path

Is {1,2,3, ... n} of one arrangement (similar to the concept of the permutation group)

M represents the determinant are asking ... (then again I do not know how to translate it directly to see the original)

 

 

The following sentence is talking about our real usefulness - when the weights of all edges are 1, and only one of the permutations and combinations are possible (ie ai-> bi)

M then the calculated value is ai-> bi program number disjoint paths. At this time, e (a, b) is a-> b of the number of program paths legitimate

 

Read the above you may still not know, in fact, what the practical problems with, you can know his routine of

 

Intersection is not allowed!
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 602    Accepted Submission(s): 195

 

Problem Description

There are K pieces on the chessboard.

The size of the chessboard is N*N.

The pieces are initially placed on the top cells of the board.

A piece located on (r, c) can be moved by one cell right to (r, c + 1) or one cell down to (r+1, c).

Your task is to count how many different ways to move all pieces to the given positions at the bottom of the board.

Furthermore, the paths of the pieces mustn’t intersect each other.

 

 

Input

The first line of input contains an integer T-the number of test cases.

Each test case begins with a line containing two integers-N(1<=N<=100000) and K(1<=K<=100) representing the size of the chessboard and the number of pieces respectively.

The second line contains K integers: 1<=a1<a2< …<aK<=N representing the initial positions of the pieces. That is, the pieces are located at (1, a1), (1, a2), …, (1, aK).

Next line contains K integers: 1<=b1<b2<…<bK<=N representing the final positions of the pieces. This means the pieces should be moved to (N, b1), (N, b2), …, (N, bK).

 

 

Output

Print consecutive T lines, each of which represents the number of different ways modulo 1000000007.

 

 

Sample Input


 
1

5 2

1 2

3 4

 

 

Sample Output


 
50

 

Meaning of the questions:

You give a matrix of n * n, then the first row starting again with k 1 <= a1 <a2 <a3 <... <ak <= n

The end of the last line n-1 <= b1 <b2 <b3 <... <bk <= n

Or you can go right down the line and asked how many programs you have, so that ai-> bi i = 1 ... n

The answer mod 1e9 + 7

 

Resolution:

e (a, b) is the number of legal program path, then we will first fill out this determinant

 

 

Then we only need to use Gaussian elimination to obtain the value of the determinant of the answer can be drawn.

That is the determinant line conversion by converting determinant to the (lower) triangular matrix, then multiply the elements on the diagonal is the answer

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long int ll;
 
const int MAXN = 2e5+10;
ll jc[MAXN];
ll inv[MAXN];
 
 
 
const ll MOD = 1e9+7;
const int N = 1e2+10;
ll a[N][N];
 
ll pow(ll a, ll n, ll p)    //快速幂 a^n % p
{
    ll ans = 1;
    while(n){
        IF (& n- . 1 ) ANS ANS = A *% P; 
        A = A * A% P; 
        n- >> = . 1 ; 
    } 
    return ANS; 
} 
 
LL niYuan (A LL, LL B)    // Fermat's little theorem of inverse element 
{
     return POW (a, B - 2 , the MOD); 
} 
 
 
inline LL C ( int a, int B)     // calculated C (a, b), at a, the B 
{
     IF (B> A) return  0 ;
     return JC [A] * INV [B]% the MOD
         * INV [ab &]% the MOD; 
}
 
void init()
{
    ll p=1;
    jc[0]=1;
    jc[1]=1;
    inv[0]=1;
    inv[1]=1;
    for(int i=2;i<MAXN;i++){
        p=(p*i)%MOD;
        jc[i]=p;
        //inv[i]=inv[MOD%i]*(MOD-MOD/i)%MOD;
    }
    
    for(int i=2; I <MAXN; I ++) INV [I] = INV [the MOD% I] * (the MOD-the MOD / I)% the MOD;    // O (n-) inversing 
    for ( int I = 2 ; I <MAXN; I ++ ) INV [i] = INV [I- . 1 ] * INV [i]% the MOD;    // ! inverse element extended to i 
} 
 
 
LL determinant ( int n-) 
{ 
    // a square matrix
     // the MOD based on availability given 
    LL = ANS . 1 ;
     for ( int K = . 1 ; K <= n-; K ++)   // a a [k + 1..n] [k ] have become 0 
    { 
        LL POS = - . 1 ;
         for ( int I K =; I <= n-; I ++)   //Find a [k..n] [k] in the first non-zero element 
            IF (A [I] [K]) 
            { 
                POS = I;
                 BREAK ; 
            } 
        IF (POS == - . 1 ) return  0 ;   // No if the determinant is 0 
        IF (! k = POS)   // will find that the wrap to the k-th row, the swap (a [k], a [POS]) 
            for ( int J = k; J <= n-; J ++ ) the swap (A [POS] [J], A [K] [J]); 
        LL INV = niYuan (A [K] [K], the MOD);
         for ( int I = K + . 1 ; I <= n-; ++ I )
             IF (A [I] [K]) 
            {
                ANS = INV *% ANS the MOD;    // the following calculations to improve the i-th row a [k] [k] times, so the answer is divided by a [k] [k] is the positive solution 
                for ( int J = K + . 1 ; J <= n-; J ++ ) 
                    A [I] [J] = ((A [I] [J] * A [K] [K]% the MOD-A [K] [J] * A [I] [K] % the MOD)% the MOD + the MOD)% the MOD; 
                A [I] [K] = 0 ; 
            } 
    } 
    for ( int I = . 1 ; I <= n-; I ++ ) 
        ANS = ANS * A [I] [I]% the MOD ;
     return ANS; 
} 
 
int A [N], B [N]; 
 
 
int main () 
{ 
    int T;
    init();
    scanf("%d",&t);
    while (t--)
    {
        int n,k;
        scanf("%d%d",&n,&k);
        for(int i=1;i<=k;i++) scanf("%d",&A[i]);
        for(int i=1;i<=k;i++) scanf("%d",&B[i]);
 
        for(int i=1;i<=k;i++)
        {
            for(int j=1;j<=k;j++)
            {
                a[i][j]=C(n+B[j]-(1+A[i]),n-1);
            }
        }
        printf("%lld\n",determinant(k));
    }
}
 
 

 

 https://blog.csdn.net/qq_36368339/article/details/81133921

 

Meaning of the questions: to give you a matrix (# indicates not go), two turtles from reaching the upper left corner of the lower right corner, the middle can not meet, how many different schemes exist, that is, the number of program two disjoint paths.
Analysis:
LGV: (https://en.wikipedia.org/wiki/Lindstr%C3%B6m%E2%80%93Gessel%E2%80%93Viennot_lemma)
PS: I do not really understand the principle, but know how to use, say, about it.
given n starting point, the n end (an end corresponding to an origin), LGV solve several major programs n * nn * n pieces paths do not intersect.
LGV is a determinant of order n, represents the starting point of the line, column Representative end, (i, j) represents the i-th to j-th starting end of the program number, the last value is the determinant of the n number of programs disjoint paths.

With LGV, the biggest trouble this problem solved. Starting with the same two turtles end, to be separated out, it is equivalent to a turtle from (1, 2), the (n - 1, m), from the other (2, 1) to (n, m --1), because the path does not intersect, do not know how you can think about.
With starting point, with the end of each number corresponds to the start of the end of each program, with the DP divert the line, and then sets LGV problem is solved.
Equivalent to two starting point, the two end points of the question, and the starting point of abscissa is 1, the abscissa is the end point n.

 

#include <stdio.h>
#include <cstring>
typedef unsigned long long LL;

const int MAXN = 3e3 + 5;
const int mod = 1e9 + 7;
LL dp[MAXN][MAXN];
char ma[MAXN][MAXN];

int main() {
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; ++i) {
        getchar();
        for(int j = 1; j <= m; ++j) {
            ma[i][j] = getchar();
        }
    }
    if(ma[1][2] == '#' || ma[2][1] == '#') {
        puts("0");
        return 0;
    }
    if(ma[1][2] != '#') dp[1][2]++;
    for(int i = 1; i <= n; ++i) {
        for(int j = 2; j <= m; ++j) {
            if(ma[i][j] != '#') dp[i][j] = (dp[i][j] + dp[i - 1][j] + dp[i][j - 1]) % mod;
        }
    }
    LL ans1 = dp[n - 1][m] % mod, ans2 = dp[n][m - 1] % mod;
    memset(dp, 0, sizeof(dp));
    if(ma[2][1] != '#') dp[2][1]++;
    for(int i = 2; i <= n; ++i) {
        for(int j = 1; j <= m; ++j) {
            if(ma[i][j] != '#') dp[i][j] = (dp[i][j] + dp[i - 1][j] + dp[i][j - 1]) % mod;
        }
    }
    LL ans3 = dp[n - 1][m] % mod, ans4 = dp[n][m - 1] % mod;
    printf("%lld\n", ((Ans4 ANS1 *)% versus - (ans2 ans3 *)% v + v)% v);
    return  0 ; 
}

 

 

https://blog.csdn.net/ftx456789/article/details/81132126

A question on the cattle off.

Guess you like

Origin www.cnblogs.com/downrainsun/p/11220334.html