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
}

原文地址:https://www.cnblogs.com/Rubbishes/p/9356880.html

时间: 2024-08-11 20:01:58

Nowcoder Monotonic Matrix ( Lindström–Gessel–Viennot lemma 定理 )的相关文章

Lindstr&#246;m–Gessel–Viennot lemma定理 行列式板子

https://blog.csdn.net/qq_37025443/article/details/86537261 博客 下面是wiki上的讲解,建议耐心地看一遍...虽然看了可能还是不懂 https://en.wikipedia.org/wiki/Lindström–Gessel–Viennot_lemma Lindström–Gessel–Viennot lemma定理是 起点集合A=(a1,a2,a3..an),终点集合B=(b1.b2,b3,..bn) 假定P是从一条从一个点到另一个点

Lindstr&#246;m–Gessel–Viennot lemma

(摘自知乎) Lindstr?m–Gessel–Viennot lemma(Lindstr?m-Gessel-Viennot lemma这里有详细介绍跟证明) 在一个有向无环图里,想要计算从n个起点 到n个终点 的n条互不相交的路径的数量(具体说是其生成函数),只要符合一定条件,就有个非常漂亮的形式表达出来.具体来说是下面一个矩阵M的行列式 其中 是从第i个起点到第j个终点的生成函数. 这里最神奇的一点是为什么结果是一个行列式.这个矩阵从线性空间的角度看完全没有意义,而实际证明过程中也完全是以组

【转】Lindstr&#246;m–Gessel–Viennot lemma 应用两则

原博客:http://www.cnblogs.com/jszkc/p/7309468.html 对于一张无边权的DAG图,给定n个起点和对应的n个终点,这n条不相交路径的方案数为 det() (该矩阵的行列式) 其中e(a,b)为图上a到b的方案数 codeforces 348D [给定一张n*m带障碍的图,求从左上角到右下角不相交两条路径的方案] [a1=(1,2) a2=(2,1) b1=(n-1,m) b2=(n,m-1) 应用该定理即可] HDU 5852 [给一张n*n的图,第一行m个

Codeforces 348 D - Turtles

D - Turtles 思路: LGV 定理 (Lindstr?m–Gessel–Viennot lemma) 从{\(a_1\),\(a_2\),...,\(a_n\)} 到 {\(b_1\),\(b_2\),...,\(b_n\)}的不相交路径数等于行列式 \[ {\left[ \begin{array}{ccc} c(a_1, b_1) & c(a_1, b_2) & ... & c(a_1, b_n) \c(a_2, b_1) & c(a_2, b_2) &

A Path Plan(2018黑龙江省赛)

又get 新知识 Lindström–Gessel–Viennot引理 改引理主要是解决n条严格不相交的路径的问题 其中ai代表路径的起点bi代表路径的终点e(ai,bj)代表ai到bj的方案数,答案是这个行列式的值 对于这道题而言,知道这个引理,这就是水题啊 code: #include <bits/stdc++.h> using namespace std; const int MOD = 1e9 + 7; typedef long long ll; const int N = 2e5 +

Matrix-Tree 定理

首先推荐 GJS学长 的这篇博文: http://www.cnblogs.com/meowww/p/6485422.html . Matrix-Tree 定理 度数矩阵 $D$ . $D_{i, i} = i 的度数$ . 邻接矩阵 $G$ . $G_{i, j}$ 表示 $i$ 到 $j$ 的连边数量. 基尔霍夫矩阵 $K$ , $K = D - G$ . 边矩阵 $B[m \times n]$ , 每行代表一条边, 对应位置的值为 $1$ . $B ^ T B = K$ . $B_i ^ T

平面分拆的 Macmahon 公式

首先看一个计数问题:一个边长为 $a\times b\times c$ 的平行六边形,每个内角都是 120 度.用边长为 1 的菱形去覆盖,有多少种不同的方法? 比如下图就是一种: 我们从上方俯视这张图(虽然这是一个平面图形,但是我们想象在空间中鸟瞰它),发现它很像是在墙角堆箱子:在一个边长为 $a\times b\times c$ 的长方体空间中堆放若干形状为单位正方体的 "箱子".不仅如此,箱子堆放的规则是有限制的:紧贴墙角处的那一摞箱子最高,从墙角向外,箱子的高度是递减的.这个规

组合数学漫游奇境记:Schur 多项式,Hook 长度公式,Macmahon 平面分拆公式

Young 表上的组合学是代数组合学中最奇妙的部分,与表示论,统计力学,概率论有着丰富而深刻的联系.这篇文章将从几个有趣的问题开始,带领大家走进这个美丽的领域.所需要的预备知识很少,学过线性代数即可,但是要真正领略其中风光,数学上的成熟是必不可少的. 需要事先剧透的是,本文要证明的几个定理绝非泛泛,它们都是代数组合学中的著名结论. 先来看几个问题: 有 $m$ 位总统候选人参加大选,他们每个人分别有 $\lambda_1,\ldots,\lambda_m$ 位支持者(假定选民只投票给他支持的候选

组合数(Lucas定理) + 快速幂 --- HDU 5226 Tom and matrix

Tom and matrix Problem's Link:   http://acm.hdu.edu.cn/showproblem.php?pid=5226 Mean: 题意很简单,略. analyse: 直接可以用Lucas定理+快速幂水过的,但是我却作死的用了另一种方法. 方法一:Lucas定理+快速幂水过 方法二:首先问题可以转化为求(0,0),(n,m)这个子矩阵的所有数之和.画个图容易得到一个做法,对于n<=m,答案就是2^0+2^1+...+2^m=2^(m+1)-1,对于n>m