题目大意:构造一个n*m的矩阵A, 满足只有0,1,2构成, 对于每一行每一列都是非递减序列的方案数模 109+7 10 9 + 7 , 数据组数不超过 105 10 5 (n,m≤103) ( n , m ≤ 10 3 )
题目思路: 考虑01和12的分界线, 实际上是两条(0,0)到(n,m)的路径, 可以重合一部分但不能交错, 考虑把其中一个分界线平移向量(1,-1), 等价于求(0,0)到(n,m)和(1,-1)到(n+1,m-1)严格不相交路径方案数。 这是一个经典问题。
科普:Lindström–Gessel–Viennot lemma定理(的一种特殊情况)
有n对点
(a1,b1),(a2,b2),...(an,bn)
(
a
1
,
b
1
)
,
(
a
2
,
b
2
)
,
.
.
.
(
a
n
,
b
n
)
, 设
e(ai,bj)
e
(
a
i
,
b
j
)
表示
ai
a
i
到
bj
b
j
的路径方案
则矩阵
⎡⎣⎢⎢⎢⎢e(a1,b1)e(a2,b1)⋮e(an,b1)e(a1,b2)e(a2,b2)⋮e(an,b2)⋯⋯⋱⋯e(a1,bn)e(a2,bn)⋮(an,bn)⎤⎦⎥⎥⎥⎥
[
e
(
a
1
,
b
1
)
e
(
a
1
,
b
2
)
⋯
e
(
a
1
,
b
n
)
e
(
a
2
,
b
1
)
e
(
a
2
,
b
2
)
⋯
e
(
a
2
,
b
n
)
⋮
⋮
⋱
⋮
e
(
a
n
,
b
1
)
e
(
a
n
,
b
2
)
⋯
(
a
n
,
b
n
)
]
的行列式的值为
ai
a
i
到
bi
b
i
的严格不相交路径的方案数。
#include <map>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
const int N = 2010;
int n, m;
const ll mo = (int)1e9 + 7;
ll ni[N];
ll pw(ll a, int p){
ll ret = 1;
while (p){
if (p & 1) ret = ret * a % mo;
a = a * a % mo;
p >>= 1;
}
return ret;
}
ll C(int n, int m){
return ni[n] * pw(ni[n - m], mo - 2) % mo * pw(ni[m], mo - 2) % mo;
}
int main(){
ni[0] = 1;
for (int i = 1; i < N; i ++)
ni[i] = ni[i - 1] * i % mo;
while (scanf("%d%d", &n, &m) != EOF){
ll ans = C(n + m, n) * C(n + m, n) % mo - C(n + m, n + 1) * C(n + m, n - 1) % mo;
ans = ((ans % mo) + mo ) % mo;
printf("%lld\n", ans);
}
return 0;
}