链接:https://www.nowcoder.com/acm/contest/139/A
来源:牛客网
Count the number of n x m matrices A satisfying the following condition modulo (109+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.
The input consists of several test cases and is terminated by end-of-file.
Each test case contains two integers n and m.
For each test case, print an integer which denotes the result.
示例1
复制
1 2
2 2
1000 1000
复制
6
20
540949876
* 1 ≤ n, m ≤ 103
* The number of test cases does not exceed 105.
#include
#include
#include
#include//int dx[4]={0,0,-1,1};int dy[4]={-1,1,0,0};
#include//int gcd(int a,int b){return b?gcd(b,a%b):a;}
#include
#include
#include
#include
#include
#include
#define ll unsigned long long
#define maxn 2005
#define MAX 500005
#define ms memset
using namespace std;
#pragma comment(linker, "/STACK:1024000000,1024000000") ///在c++中是防止暴栈用的
const int mod=(1e9+7);
/*
题目大意:给定一个矩阵的规模,
计数用0,1,2来填充的个数,
其中满足数学要求。。。(题目中见)
首先要有组合数学不相交路径的知识,(下面转发的)
Lindström–Gessel–Viennot Lemma
作为一个特殊情况,引理提供对给定一个起点终点对集(记起点集为 AA 终点集为 BB ,且路径为 ai→biai→bi ),统计不相交路径数。
引理的内容如下:
令 ω(P):=ω(P):= 路径 PP 的边权积, e(a,b):=∑P:a→bω(P)e(a,b):=∑P:a→bω(P) ,
M:=(e(a1,b1)e(a1,b2)⋯e(a1,bm) e(a2,b1)e(a2,b2)⋯e(a2,bm) ⋮⋮⋱⋮ e(an,b1)e(an,b2)⋯e(an,bm))M:=(e(a1,b1)e(a1,b2)⋯e(a1,bm) e(a2,b1)e(a2,b2)⋯e(a2,bm) ⋮⋮⋱⋮ e(an,b1)e(an,b2)⋯e(an,bm))
该引理宣称,det|M|det|M| 给出AA 到 BB 不相交路径的权值和。
特殊情况,令各边边权为11 ,此时|M||M| 为不相交路径数。
更一般情况,ωω 可以是形式变量,则 ee 将成为形式幂级数。
假定我们在网格图中,从第 11 行的起点走到第 nn 的终点。
首先假设我们只有两对点 (a1,b1),(a2,b2)(a1,b1),(a2,b2) ,不考虑相交,则总路径数为 (b1−a1+n−1n−1)(b2−a2+n−1n−1)(b1−a1+n−1n−1)(b2−a2+n−1n−1) .
考虑 a1→b1,a2→b2a1→b1,a2→b2 相交,则在最后一个相交点之后交换路径,则得到 a1→b2,a2→b1a1→b2,a2→b1 的路径。
考虑 a1→b2,a2→b1a1→b2,a2→b1 的路径,其必相交,则在最后一个相交点之后交换路径。
此时我们建立了 a1→b1,a2→b2a1→b1,a2→b2 的相交路径与 a1→b2,a2→b1a1→b2,a2→b1 的一一对应。
所以除去不合法情况后,答案为 (b1−a1+n−1n−1)(b2−a2+n−1n−1)−(b1−a2+n−1n−1)(b2−a1+n−1n−1)(b1−a1+n−1n−1)(b2−a2+n−1n−1)−(b1−a2+n−1n−1)(b2−a1+n−1n−1) .
接着考虑多组路径,使用容斥原理。
假设某些路径相交,则在最后一个相交点之后交换路径,得到 BB 的重排 CC .
所以我们只需考虑 CC 的逆序对数,为奇数则贡献为负,否则为正。
展开写,发现这就是一个行列式。
有了这个,可以从四个点的坐标,(n,0),(n-1,-1),(0,m),(-1,m-1)四个点分别为起点和终点。
那么行列式就显然了。
下面我们要计算逆元,由于阶乘的逆元的特殊,所以用快速幂打表即可。
*/
ll Pow(ll a,ll b)
{
ll t=1;
while(b>0)
{
if(b&1) t=t*a%mod;
a=a*a%mod;
b>>=1;
}
return t;
}
ll jie[maxn],inv[maxn];
void get_jie()
{
jie[0]=1;
for(int i=1;i