There are K pieces on the chessboard.

The size of the chessboard is N*N.

The pieces are initially placed on the top cells of the board.

A piece located on (r, c) can be moved by one cell right to (r, c + 1) or one cell down to (r+1, c).

Your task is to count how many different ways to move all pieces to the given positions at the bottom of the board.

Furthermore, the paths of the pieces mustn’t intersect each other.

InputThe first line of input contains an integer T-the number of test cases.

Each test case begins with a line containing two
integers-N(1<=N<=100000) and K(1<=K<=100) representing the
size of the chessboard and the number of pieces respectively.

The second line contains K integers: 1<=a1<a2<
…<aK<=N representing the initial positions of the pieces. That is,
the pieces are located at (1, a1), (1, a2), …, (1, aK).

Next line contains K integers: 1<=b1<b2<…<bK<=N
representing the final positions of the pieces. This means the pieces
should be moved to (N, b1), (N, b2), …, (N, bK).

OutputPrint consecutive T lines, each of which represents the number of different ways modulo 1000000007.Sample Input

1
5 2
1 2
3 4

Sample Output

50

数学问题 容斥 矩阵行列式 脑洞题

假如只有一个起点一个终点,显然是一个基本的组合数问题,从所有步数中选n-1步向下走,方案为 $ ans = C(b-a+n-1,n-1) $

如果有两个起点两个终点,则是总方案数减去路径交叉的方案数。路径相交可以理解为两人交换了目的地,所以方案为

  $ ans = C(b_1-a_1+n-1,n-1)*C(b_2-a_2+n-1,n-1) - C(b_1-a_2+n-1,n-1)*C(b_2-a_1+n-1,n-1)$

显然枚举起点和终点有几对逆序对,可以容斥计算出答案,显然这样TLE了

但这个逆序对数量决定加还是减的容斥可以让我们联想到另一个东西——矩阵行列式。

从矩阵的每一行选一列,将选的每一个位置的值乘起来,乘以(-1)^(逆序对数),即是这一部分对行列式值的贡献,所有的选法的贡献叠加起来,就是矩阵行列式的值。

那么我们只要将每个(u to v)的关系用矩阵表示,再求矩阵行列式的值就是答案了。

 /*by SilverN*/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#define LL long long
using namespace std;
const int mxn=;
const int mod=1e9+;
int read(){
int x=,f=;char ch=getchar();
while(ch<'' || ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>='' && ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int fac[mxn],inv[mxn];
void init(){
fac[]=fac[]=;inv[]=inv[]=;
for(int i=;i<mxn;i++){
fac[i]=(LL)fac[i-]*i%mod;
inv[i]=((-mod/i*(LL)inv[mod%i])%mod+mod)%mod;
}
for(int i=;i<mxn;i++)inv[i]=(LL)inv[i]*inv[i-]%mod;
return;
}
int ksm(int a,int k){
int res=;
while(k){
if(k&)res=(LL)res*a%mod;
a=(LL)a*a%mod;
k>>=;
}
return res;
}
int f[][];
int Gauss(int n){
int ft=;
for(int i=;i<=n;i++){
if(!f[i][i]){
int p=i;
for(int j=i+;j<=n;j++)if(f[j][i]){p=j;break;}
if(p==i)return ;
for(int j=i;j<=n;i++)swap(f[i][j],f[p][j]);
ft=-ft;
}
int IV=ksm(f[i][i],mod-);
for(int j=i+;j<=n;j++){
int tmp=(LL)f[j][i]*IV%mod;
for(int k=i;k<=n;k++){
f[j][k]=((LL)f[j][k]-(LL)tmp*f[i][k])%mod;
}
}
}
int res=ft;
for(int i=;i<=n;i++){
res=(LL)res*f[i][i]%mod;
}
return (res+mod)%mod;
}
int n,K;
int a[mxn],b[mxn];
int C(int n,int m){
if(n<m)return ;
return (LL)fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int path(int x,int y){
return (LL)C(b[y]-a[x]+n-,n-);
}
void solve(){
memset(f,,sizeof f);
for(int i=;i<=K;i++){
for(int j=;j<=K;j++){
f[i][j]=path(i,j);
}
}
int ans=Gauss(K);
printf("%d\n",ans);
return;
}
int main(){
// freopen("in.txt","r",stdin);
init();
int T=read(),i;
while(T--){
n=read();K=read();
for(i=;i<=K;i++)a[i]=read();
for(i=;i<=K;i++)b[i]=read();
solve();
}
return ;
}

HDU5852 Intersection is not allowed!的更多相关文章

  1. hdu5852 Intersection is not allowed! 【矩阵行列式】

    题意 给出\(n*n\)网格\((n<=10^5)\) 顶部有\(K\)个起点,底部有\(K\)个相对应的终点 每次只能向下或向右走 求有多少种从各个起点出发到达对应终点且路径不相交的路径? 对 ...

  2. HDU 5852 Intersection is not allowed!(LGV定理行列式求组合数)题解

    题意:有K个棋子在一个大小为N×N的棋盘.一开始,它们都在棋盘的顶端,它们起始的位置是 (1,a1),(1,a2),...,(1,ak) ,它们的目的地是 (n,b1),(n,b2),...,(n,b ...

  3. hdu 5852 :Intersection is not allowed! 行列式

    有K个棋子在一个大小为N×N的棋盘.一开始,它们都在棋盘的顶端,它们起始的位置是 (1,a1),(1,a2),...,(1,ak) ,它们的目的地是 (n,b1),(n,b2),...,(n,bk). ...

  4. HDU 5852 Intersection is not allowed! ( 2016多校9、不相交路径的方案、LGV定理、行列式计算 )

    题目链接 题意 : 给定方格中第一行的各个起点.再给定最后一行与起点相对应的终点.问你从这些起点出发到各自的终点.不相交的路径有多少条.移动方向只能向下或向右 分析 : 首先对于多起点和多终点的不相交 ...

  5. LGV 引理

    (其实是贺的:https://www.luogu.com.cn/paste/whl2joo4) 目录 LGV 引理 不相交路径计数 例题 Luogu6657. [模板]LGV 引理 CF348D Tu ...

  6. FJNU2018低程A 逃跑路线(Lucas + 中国剩余定理 + LGV定理)题解

    题目描述 n个人在w*h的监狱里面想要逃跑,已知他们的同伙在坐标(bi,h)接应他们,他们现在被关在(ai,1)现在他们必须要到同伙那里才有逃出去的机会,这n个人又很蠢只会从(x,y)->(x+ ...

  7. 2016 Multi-University Training Contest 9 solutions BY 金策工业综合大学

    A Poor King Tag: Reversed BFS Preprocessing is needed to calculate answers for all positions (states ...

  8. Lindström–Gessel–Viennot lemma定理 行列式板子

    https://blog.csdn.net/qq_37025443/article/details/86537261 博客 下面是wiki上的讲解,建议耐心地看一遍...虽然看了可能还是不懂 http ...

  9. IIS7.5上的REST服务的Put,Delete操作发生HTTP Error 405.0 - Method Not Allowed 解决方法

    WebDAV 是超文本传输协议 (HTTP) 的一组扩展,为 Internet 上计算机之间的编辑和文件管理提供了标准.利用这个协议用户可以通过Web进行远程的基本文件操作,如拷贝.移动.删除等.在I ...

随机推荐

  1. 算法与数据结构3.3 calculator

    ★实验任务 小 V 发明了一个神奇的整数计算器: 给定一个合法的表达式,这个计算器能求出这个表达式的最终答案. 表达式可能包含: +:运算符,整数加法.如 1+1=2 -:运算符,整数减法.如 1-1 ...

  2. Java之I/O流(第1部分)

    Java 中的I/O流: 1. 输入/输出流原理: 如下图所示:在 java 程序中,对于数据的输入/输出操作以“流”(Stream)的方式进行:J2SDK 提供了各种各样的“流”类,用来获取不同种类 ...

  3. lintcode-142-O(1)时间检测2的幂次

    142-O(1)时间检测2的幂次 用 O(1) 时间检测整数 n 是否是 2 的幂次. 样例 n=4,返回 true; n=5,返回 false. 挑战 O(1) time 标签 比特位操作 思路 使 ...

  4. 多个表单数据提交下的serialize()应用

    在实际开发场景中,难免遇到需要多个表单的数据传递问题. 之所以要进行多表单的数据传递是因为可以进行数据分组,便于数据的维护. 这个时候,出于不依赖jquery的考虑,有一个原生js函数来解决这个问题无 ...

  5. getGeneratedKeys自动获取主键的方法

    public class Demo { public static void main(String[] args) { try { String sql="insert into pers ...

  6. 【bzoj4229】选择 离线+LCT

    题目描述 现在,我想知道自己是否还有选择. 给定n个点m条边的无向图以及顺序发生的q个事件. 每个事件都属于下面两种之一: 1.删除某一条图上仍存在的边 2.询问是否存在两条边不相交的路径可以从点u出 ...

  7. Python单例模式的四种方法

    在这之前,先了解super()和__new__()方法 super()方法: 返回一个父类或兄弟类类型的代理对象,让你能够调用一些从继承过来的方法. 它有两个典型作用: a. 在单继承的类层次结构中, ...

  8. NetScaler + Wireshark = A Perfect Combination!

    NetScaler + Wireshark = A Perfect Combination! https://www.citrix.com/blogs/2014/05/03/netscaler-wir ...

  9. 【转】PowerDesigner中Table视图同时显示Code和Name

    为避免图片失效,文字描述, Tools-Display Preference-->左侧Table-->右下角Advanced-->左侧树Columns-->右侧上面第一个放大镜 ...

  10. [洛谷P2511][HAOI2008]木棍分割

    题目大意:有$n(n\leqslant5\times10^4)$根木棍,连续放在一起,把它们分成$m(\leqslant10^3)$段,要求使得最长的段最短,问最短的长度以及方案数 题解:要使得最长的 ...