题目
思路
《尝试集》
显然是要减去所有相交的路径。
考虑枚举最后一个相交的点,那么其前面可以乱走,后面必须不相交。
用 表示,从 走到 和 的不相交——除了在起点 上相交——的路线数量。则
这个式子的意义是枚举最后一个相交的点。把 换成 ,把 换成 ,把 换成 ,把 换成 ,把 换成 ,我们有
那么这道题中,我们需要计算
两个式子的形式挺相近的。但是我化简不动了。不过讲道理肯定是正确的式子。
《飞鸟集》
考虑两条相交的路径。如果不考虑对应关系,它更像一个乱糟糟的毛线团——前面有两个端头,后面也有两个端头,中间搅在一块。
当然,我们可以先把毛线团的结构确定,然后再把颜色染上去。所以我们可以 交换对应关系。不难发现相交的路径数量就是 。
代码
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
typedef long long int_;
inline int readint(){
int a = 0; char c = getchar(), f = 1;
for(; c<'0'||c>'9'; c=getchar())
if(c == '-') f = -f;
for(; '0'<=c&&c<='9'; c=getchar())
a = (a<<3)+(a<<1)+(c^48);
return a*f;
}
inline void writeint(int x){
if(x > 9) writeint(x/10);
putchar((x%10)^48);
}
inline int qkpow(int_ b,int q,int m){
int ans = 1;
for(; q; q>>=1,b=b*b%m)
if(q&1) ans = ans*b%m;
return ans;
}
const int MaxN = 200005;
const int Mod = 1e9+7;
int jc[MaxN], inv[MaxN];
void prepare(){
jc[1] = inv[1] = 1;
for(int i=2; i<MaxN; ++i){
jc[i] = 1ll*jc[i-1]*i%Mod;
inv[i] = (0ll+Mod-Mod/i)*inv[Mod%i]%Mod;
}
for(int i=2; i<MaxN; ++i)
inv[i] = 1ll*inv[i]*inv[i-1]%Mod;
jc[0] = inv[0] = 1;
}
int_ C(int n,int m){
if(n < m) return 0; // 拿不出来
return 1ll*jc[n]*inv[m]%Mod*inv[n-m]%Mod;
}
int main(){
prepare();
for(int T=readint(); T; --T){
int x1 = readint(), x2 = readint();
int y1 = readint(), y2 = readint();
int_ all = C(x1+y1,y1)*C(x2+y2,y2)%Mod;
int_ bad = C(x1+y2,y2)*C(x2+y1,y1)%Mod;
all = (all+Mod-bad)%Mod;
printf("%lld\n",all);
}
return 0;
}