A Monotonic Matrix
学习一下Lindström–Gessel–Viennot lemma,有一个没听说过的数学,这数学场是要慢慢学习;
一种计算非交叉格子路径数的方法:
主要公式就是对于一张无边权的DAG图,给定n个起点和对应的n个终点,这n条不相交路径的方案数为:
题目:在所有的n*m的矩阵中,数出满足条件的矩阵的数量(% 1e9+7)
* Ai, j ∈ {0, 1, 2} for all 1 ≤ i ≤ n, 1 ≤ j ≤ m.
* Ai, j ≤ Ai + 1, j for all 1 ≤ i < n, 1 ≤ j ≤ m.
* Ai, j ≤ Ai, j + 1 for all 1 ≤ i ≤ n, 1 ≤ j < m.
考虑到01 和 12分界线
就是(n,0)到(0,m)的两条不相交(可重合)的路线;
平移其中一条,变成(n-1,-1)到(-1,m-1)
变成起点(n,0)和(n-1,-1),终点(0,m)和(-1,m-1)的严格不相交路径
套用公式就是C(n+m,n) ^ 2 - C(n+m,m-1)*C(n+m,n-1)
代码(补):
/*************************************************************************
> File Name: a.cpp
> Author:
> Mail:
> Created Time: 2018年07月20日 星期五 12时34分13秒
************************************************************************/
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 3e3+7;
const ll mod = 1e9+7;
int n, m;
ll c[maxn][maxn];
void init()
{
memset(c, 0, sizeof(c));
for(int i = 1; i < maxn; i++) c[i][0] = 1, c[i][i] = 1;
for(int i = 2; i < maxn; i++)
for(int j = 1; j < i; j++)
c[i][j] = (c[i-1][j-1] + c[i-1][j])%mod;
}
int main()
{
init();
//freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &n, &m))
{
printf("%lld\n", (c[n+m][n]*c[n+m][n]%mod - c[n+m][m-1]*c[n+m][n-1]%mod + mod)%mod);
}
return 0;
}