Nowcoder Monotonic Matrix ( Lindström–Gessel–Viennot lemma 定理 )

题目链接

题意 : 在一个 n * m 的矩阵中放置 {0, 1, 2} 这三个数字、要求 每个元素 A(i, j) <= A(i+1, j) && A(i, j) <= A(i, j+1) 、问你合法的构造方案有多少种

 

分析 :

分析一下限制条件不难得出、其实就是在矩阵中设置两条分界线

使得分界线总左上角到右下角分别是 0、1、2 例如如下的矩阵就是合法的

0 0 1 2

0 1 2 2

1 2 2 2

那么问题就转化成了在矩阵中找出两条可重叠的路径

把矩阵分成三个部分

有一个 Lindström–Gessel–Viennot lemma 定理就是专门做这件事情的

具体可以看看这篇博客 ==> click here

但是这个定理只适用于不相交的路径

但是我们这个题目下路径是可以重叠的、也算相交的一种

那么需要采用等价转化的方法来避免相交

此题可以采用将第二条路径整体平移的方法、将终点和起点都整体向右下平移

这并不会干扰方案数、然后根据平移后的起点终点就能计算行列式了 ==> click here

 

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;
const int maxn = 2e3 + 10;
const LL mod = 1e9 + 7;

LL c[maxn][maxn];

inline void init()
{
    for(int i=1; i<=maxn-10; i++){
        c[i][0] = c[i][i] = 1;
        for(int j=1; j<i; j++){
            c[i][j] = (c[i-1][j]%mod + c[i-1][j-1]%mod)%mod;
        }
    }
}

int main(void){__stTIME();__IOPUT();


    int n, m;

    init();

    while(~scii(n, m)){
        printf("%lld\n",
               ( ( (c[n+m][n]%mod * c[n+m][n]%mod)%mod -
                   (c[n+m][m-1]%mod * c[n+m][m+1]%mod)%mod ) + mod ) % mod);
    }


__enTIME();return 0;}


void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}
View Code

 

posted @ 2018-07-23 20:57  qwerity  阅读(188)  评论(0编辑  收藏  举报