zoukankan      html  css  js  c++  java
  • 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
    ",
                   ( ( (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
  • 相关阅读:
    剑指 Offer——13. 调整数组顺序使奇数位于偶数前面
    剑指 Offer——3. 从尾到头打印链表
    剑指 Offer——2. 替换空格
    剑指 Offer——1. 二维数组中的查找
    LeetCode 905. Sort Array By Parity 按奇偶校验排列数组
    LeetCode 448. Find All Numbers Disappeared in an Array找到所有数组中消失的元素
    SSH 代码笔记
    anaconda3安装caffe
    opencv多版本安装
    人脸文章与数据库
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/9356880.html
Copyright © 2011-2022 走看看