牛客网多校训练第一场 A - Monotonic Matrix(Lindström–Gessel–Viennot lemma)

链接:

https://www.nowcoder.com/acm/contest/139/A

 

题意:

求满足以下条件的n*m矩阵A的数量模(1e9+7):
A(i,j) ∈ {0,1,2}, 1≤i≤n, 1≤j≤m.
A(i,j) ≤ A(i+1,j), 1≤i<n, 1≤j≤m.
A(i,j) ≤ A(i,j+1), 1≤i≤n, 1≤j<m.
其中1 ≤ n,m ≤ 1e3。

 

分析:

考虑01和12的分界线,
是(n,0)到(0,m)的两条不相交(可重合)路径。
平移其中一条变成(n+1,1)到(1,m+1),
变成(n,0)到(0,m)、(n+1,1)到(1,m+1)的严格不相交路径。
套Lindström–Gessel–Viennot lemma,
答案是C(n+m,n) * C(n+m,n) - C(n+m,n+1) * C(n+m,n-1)。

 

Lindström–Gessel–Viennot lemma简介:

求a1到b1, a2到b2, ..., an到bn的严格不相交路径种数。

计算以上矩阵的行列式即可,其中e(a,b)是从a到b的方法数。

 

代码:

 1 #include <cstdio>
 2 
 3 typedef long long int LLI;
 4 const int UP = 1000 * 2 + 5;
 5 const LLI MOD = 1e9 + 7;
 6 LLI f[UP]; // 阶乘
 7 
 8 LLI qmod(LLI x, LLI n, LLI mod) { // 快速幂模
 9     x %= mod;
10     LLI res = 1;
11     while(n) {
12         if(n & 1) res = res * x % mod;
13         n >>= 1;
14         x = x * x % mod;
15     }
16     return res;
17 }
18 
19 LLI inv(LLI a, LLI mod) { // 逆元
20     return qmod(a, mod-2, mod);
21 }
22 
23 void constant() { // 预处理阶乘
24     f[0] = 1;
25     for(int i = 1; i < UP; i++) f[i] = f[i-1] * i % MOD;
26 }
27 
28 LLI C(int n, int m) { // 组合数,从n个里取m个
29     return f[n] * inv(f[m]*f[n-m], MOD) % MOD;
30 }
31 
32 int main() {
33     constant();
34     int n, m;
35     while(~scanf("%d%d", &n, &m)) {
36         LLI ans = (C(n+m,n) * C(n+m,n) - C(n+m,n+1) * C(n+m,n-1) % MOD + MOD) % MOD;
37         printf("%lld\n", ans);
38     }
39     return 0;
40 }

 

posted @ 2018-07-23 04:33  Ctfes  阅读(177)  评论(0编辑  收藏  举报