这是一道公式题,虽然想了半天也想不出来,https://en.wikipedia.org/wiki/Lindström–Gessel–Viennot_lemma看这个就行了。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=200005;
const int mod=1000000007;
int jie[maxn];
int jie1[maxn];
int mm(int n,int m){
LL s=1;
LL k=n;
while(m){
if(m&1){
s=s*k;
s%=mod;
}
k=k*k;
k%=mod;
m>>=1;
}
return s;
}
void init(){
jie[0]=1;
jie1[0]=1;
for(int i=1;i<maxn;i++){
jie[i]=((LL)jie[i-1]*i)%mod;
jie1[i]=mm(jie[i],mod-2);
}
}
int zuhe(int n,int m){
if(n<m) return 0;
LL s=jie[n];
s=s*jie1[n-m];
s%=mod;
s=s*jie1[m];
s%=mod;
return s;
}
int a[maxn],b[maxn];
int mat[500][500];
int gcd(int a,int b){
if(b==0) return a;
return gcd(b,a%b);
}
int Gauss(int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
mat[i][j] = (mat[i][j] + mod) % mod;
}
int col = 0, k;
LL ans = 1;
for(k = 0; k < n && col < n; ++k, ++col) {
if(mat[k][col] == 0) {
for(int i = k + 1; i < n; ++i) {
if(!(mat[i][col] == 0)) {
for(int j = col; j < n; ++j) swap(mat[k][j], mat[i][j]);
ans *= -1;
break;
}
}
}
int x = mat[k][col];
ans *= x;
ans %= mod;
for(int i = k + 1; i < n; ++i) {
int y = mat[i][col];
if(x == 0 || y == 0) continue;
int d = gcd(abs(x),abs(y));
LL lcm = abs((LL)x * y / d);
LL tx = lcm / x,ty = lcm / y;
for(int j = col; j < n; ++j) {
mat[i][j] = (-tx * mat[k][j] + ty * mat[i][j])%mod;
}
ans = (ans * mm(ty,mod-2)) % mod;
}
}
ans %= mod;
ans += mod;
ans %= mod;
return ans;
}
int main()
{
int t,n,m;
cin>>t;
init();
while(t--){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
for(int i=1;i<=m;i++){
for(int j=1;j<=m;j++){
mat[i-1][j-1]=zuhe(b[j]-a[i]+n-1,n-1);
}
}
printf("%d\n",Gauss(m));
}
}