Problem Description
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.
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.
Input
The 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).
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).
Output
Print 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
题意:
给你两个长度为K的数列x[ ] ,y [ ] 。表示在N*N的棋盘,最开始有K个棋子在(1,x[1] ) ,(1,x[2] ),,,,,,(1,x[K])处。要将K个棋子移动到(N,y[1] ) ,(N,y[2] ),,,,,,(N,y[K])处.并且每个棋子的路径不能相交。求移动种数。只能向下和向右移动。
分析:这里有个结论,K个点在有向无环图中移动到另外K个点。每个点移动路径不能相交。移动种数为。每个起点移动到每个终点的全部移动种数组成一个K*K行列式。行列式的值就是所求。
代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define eps 1e-6
typedef long long ll;
const ll mod = 1e9+7;
const int N = 2e5+10;
ll inv[N] = {1,1}; //inv[i] i的逆元。
ll fac[N] = {1,1}; // fac[i] i!%mod
ll facv[N] = {1,1}; // facv[i] i!的逆元
void init()
{
for(int i = 2 ; i < N ; i ++)
inv[i] = (mod-mod/i) * inv[mod%i] % mod;
for(int i = 2 ; i < N ; i ++)
facv[i] = facv[i-1] * inv[i] % mod;
for(int i = 2 ; i < N ; i ++)
fac[i] = fac[i-1]*i % mod;
}
ll C(ll n,ll m)
{
if(m < 0) return 0;
return fac[n]*facv[m]%mod*facv[n-m]%mod;
}
int s[110],e[110];
ll a[110][110];
ll det(int n)
{
ll ans=1;
int sign = 0;
for(int i=0;i<n;i++)//当前行
{
for(int j=i+1;j<n;j++)//当前之后的每一行,因为每一行的当前第一个数要转化成0(想想线性代数中行列式的计算)
{
int x=i,y=j;
while(a[y][i])//利用gcd的方法,不停地进行辗转相除
{
ll t=a[x][i]/a[y][i];
for(int k=i;k<n;k++)
a[x][k]=(a[x][k]-a[y][k]*t)%mod;
swap(x,y);
}
if(x!=i)//奇数次交换,则D=-D'整行交换
{
for(int k=0;k<n;k++)
swap(a[i][k],a[x][k]);
sign^=1;
}
}
if(a[i][i]==0)//斜对角中有一个0,则结果为0
{
return 0;
}
else
ans=ans*a[i][i]%mod;
}
if(sign!=0)
ans*=-1;
if(ans<0)
ans+=mod;
return ans;
}
int main()
{
int n,k,t;
init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&k);
for(int i = 0 ; i < k ; i ++)
scanf("%d",&s[i]);
for(int i = 0 ; i < k ; i ++)
scanf("%d",&e[i]);
for(int i = 0 ; i < k ; i ++)
{
for(int j = 0 ; j < k ; j ++)
{
a[i][j] = C(n-1+e[j]-s[i],e[j]-s[i]);
}
}
printf("%lld\n",det(k));
}
return 0;
}