给定n个起点和对应的n个终点,这n条不相交路径的方案数为

本文介绍了一个算法问题,即计算满足特定条件的n×m矩阵的数量。矩阵中的元素必须在0到2之间,且遵循行和列的递增规则。通过使用组合数学原理,文章提供了求解该问题的代码实现,包括阶乘、逆元的快速幂计算以及最终结果的求解。

题目描述
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 2
2 2
1000 1000
样例输出
6
20
540949876

提示

  • 1 ≤ n, m ≤ 103
  • The number of test cases does not exceed 105.

这张图片是网上到处流传的一张图片定理, 虽然我也不懂, 但是我可以理解一下
在这里插入图片描述
求以上矩阵的行列式,其中 e(a,b) 是从a到b的方法数,带入求行列式即可得到(a1,a2,…an) 到 (b1,b2,…bn) 的所有不相交路径的种数

考虑01和12的分界线是(n, 0)到(0,m)的两条不相交(可重合)路径,
分界线以及分界线以上的点是一种,分界线下是一种
平移其中一条变成(n-1, -1)到(-1,m-1);

在这里插入图片描述
在这里插入图片描述
来源
然后就直接求阶乘,求逆元, 然后按照这个行列式乘一下就行了

#include <iostream>
using namespace std;
const int N = 2e3 + 10 ;
const int mod = 1e9 + 7 ; 
typedef long long ll ;
ll f[N] , ff[N];
ll qmi(ll a, ll b)
{
	ll res = 1 ;
	while(b)
	 {
	 	if(b & 1) res = res * a % mod ;
	 	a = a * a % mod ;
	 	b >>= 1 ;
	 }
	 return res ;
}
void init()
{
	f[0] = 1 , ff[0] = 1 ;
	for(int i = 1 ;i < N ;i ++)
	 f[i] = f[i - 1] * i % mod , ff[i] = qmi(f[i] , mod - 2) ;
}
int main()
{
	init() ;
	ll n , m ;
	while(scanf("%lld%lld" , &n , &m) != EOF)
	 {
	 	ll ans = (f[n + m] * ff[n] % mod * ff[m]) % mod ;
	 	ans = ans * ans % mod ;
	 	ans = ans - f[n + m] * ff[n - 1] % mod * f[n + m] % mod * ff[n + 1] * ff[m + 1] % mod * ff[m - 1] % mod ;
	 	ans = (ans + mod) % mod ;
	 	printf("%lld\n" , ans) ;
	 }
	return 0 ;
} 

A Path Plan

直接照着模板写

#include <iostream>
using namespace std;
typedef long long ll ;
const int N = 2e5 + 10 ;
const int mod = 1e9 + 7 ;
ll f[N] , ff[N] ;
ll qmi(ll a , ll b)
{
	ll res = 1 ;
	while(b)
	{
		if(b & 1) res = res * a % mod ;
		a = a * a % mod ;
		b >>= 1 ;
	}
	return res ;
}
void init()
{
	f[0] = ff[0] = 1 ;
	for(int i = 1 ;i < N ;i ++)
	 f[i] = f[i - 1] * i % mod , ff[i] = qmi(f[i] , mod - 2) ;
	return ; 
}
int main()
{
	int t ;
	cin >> t ;
	init() ;
	while(t --)
	 {
	 	int x1 , x2 , y1 , y2 ;
	 	cin >> x1 >> x2 >> y1 >> y2 ;
	 	ll ans = f[x1 + y1] % mod * ff[x1] % mod * ff[y1] % mod ;
	 	ans = ans * f[x2 + y2] % mod * ff[x2] % mod * ff[y2] % mod ;
	 	ans -= f[x2 + y1] % mod * ff[x2] % mod * ff[y1] % mod * f[x1 + y2] % mod * ff[x1] % mod * ff[y2] % mod ;
	 	printf("%lld\n" , (ans + mod) % mod) ;
	 }
	return 0 ;
}
小 A 被困在一个 N×N 的方形迷宫中,每个房间的中心都标有一个整数,范围在 0 到 K-1 之间。初始时,你们位于左上角的房间 (0,0),目标是通过一系列移动到达右下角的房间 (N-1,N-1)。迷宫的规则如下: 挑战者从初始房间 (0,0) 出发,终点是右下角的 (N-1,N-1) 处的格子,每一步可以选择沿着水平/垂直/对角线的方向移动到下一个格子。 经过的房间数字必须严格按顺序循环:0,1,2,…,K-1,0,1,2,…,K-1,0,1,2,… 。 途中对迷宫每一个房间恰好都经过一次(仅一次)。 路径中不可以出现交叉路线,比如之前从 (0,0) 移动到 (1,1),那么再从 (1,0) 移动到 (0,1) 的线路就会出现交叉。 为方便表示,对可以行进的所有八个方向进行了数字编号(示例图略);行进路径可用包含 0…7 之间数字的字符串表示,如迷宫示例对应答案是 41255214。 图片1.png 现请你帮小 A 规划行进路径并输出。若有多路径,输出字典序最小的;若不存在路径,输出 -1。 你小 A 被困在一个 N×N 的方形迷宫中,每个房间的中心都标有一个整数,范围在 0 到 K-1 之间。初始时,你们位于左上角的房间 (0,0),目标是通过一系列移动到达右下角的房间 (N-1,N-1)。迷宫的规则如下: 挑战者从初始房间 (0,0) 出发,终点是右下角的 (N-1,N-1) 处的格子,每一步可以选择沿着水平/垂直/对角线的方向移动到下一个格子。 经过的房间数字必须严格按顺序循环:0,1,2,…,K-1,0,1,2,…,K-1,0,1,2,… 。 途中对迷宫每一个房间恰好都经过一次(仅一次)。 路径中不可以出现交叉路线,比如之前从 (0,0) 移动到 (1,1),那么再从 (1,0) 移动到 (0,1) 的线路就会出现交叉。 为方便表示,对可以行进的所有八个方向进行了数字编号(示例图略);行进路径可用包含 0…7 之间数字的字符串表示,如迷宫示例对应答案是 41255214。 图片1.png 现请你帮小 A 规划行进路径并输出。若有多路径,输出字典序最小的;若不存在路径,输出 -1。 输出一行表示答案。若存在答案输出路径,否则输出 -1。 用c++实现
07-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值