首先我们只会计算的情况是,给定起点和终点,计算从起点到终点的路径条数。由于起点和终点都是不确定的,因此显然不能直接计算。
我们考虑,从一个点走到一个矩形区域的方案数是多少呢?
设 F x , y F_{x,y} Fx,y表示从 ( 0 , 0 ) (0,0) (0,0)走到 ( x , y ) (x,y) (x,y)的方案数。那么我们有: F x , y = ∑ i = 0 y F x − 1 , i F_{x,y}=\sum_{i=0}^yF_{x-1,i} Fx,y=∑i=0yFx−1,i
这个式子极具启发意义。它告诉我们,可以用到一个位置的方案数,来表示到一堆位置的方案数。这个思想非常重要。
于是我们得到了从 ( 0 , 0 ) (0,0) (0,0)到左下角为 ( a , b ) (a,b) (a,b),右上角为 ( c , d ) (c,d) (c,d)的矩形区域的方案数: F c + 1 , d + 1 − F a , d + 1 − F c + 1 , b + F a , b F_{c+1,d+1}-F_{a,d+1}-F_{c+1,b}+F_{a,b} Fc+1,d+1−Fa,d+1−Fc+1,b+Fa,b 。
那么问题转化为给定起点和终点,经过中间矩形区域其中一个点的方案数。我们枚举进入和出去中间矩阵的位置,那么能被选为中转点的数目就是这两个点的曼哈顿距离,注意到坐标是可以分离的,因此将贡献拆开计算即可。
复杂度 O ( n ) O(n) O(n)。
#include<bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define pb push_back
#define inf 0x3f3f3f3f
#define int ll
using namespace std;
const int mod=1e9+7;
const int N=2e6+5;
int X1,X2,X3,X4,X5,X6,Y1,Y2,Y3,Y4,Y5,Y6;
int fac[N],inv[N],res;
struct node{
int X,Y,Z;
};
vector<node>v1,v2;
int fpow(int x,int y){
int z(1);
for(;y;y>>=1){
if(y&1)z=z*x%mod;
x=x*x%mod;
}return z;
}
void init(int n){
fac[0]=1;for(int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;
inv[n]=fpow(fac[n],mod-2);for(int i=n;i>=1;i--)inv[i-1]=inv[i]*i%mod;
}
int binom(int x,int y){
return fac[x]*inv[y]%mod*inv[x-y]%mod;
}
int G(int a,int b,int c,int d){
assert(a<=c),assert(b<=d);
return binom(c+d-a-b,c-a);
}
int solve(int A,int B,int C,int D){
ll res=0;
res=(res-G(A,B,X3,Y3)*(X3+Y3)%mod*G(X3,Y3,C,D)%mod)%mod;
for(int i=X3+1;i<=X4;i++){
res=(res-G(A,B,i,Y3-1)*(i+Y3)%mod*G(i,Y3,C,D)%mod)%mod;
}
for(int i=Y3+1;i<=Y4;i++){
res=(res-G(A,B,X3-1,i)*(X3+i)%mod*G(X3,i,C,D)%mod)%mod;
}res=(res+(X4+Y4+1)*G(X4,Y4,C,D)%mod*G(A,B,X4,Y4)%mod)%mod;
for(int i=X4-1;i>=X3;i--){
res=(res+G(i,Y4+1,C,D)*(i+Y4+1)%mod*G(A,B,i,Y4)%mod)%mod;
}
for(int i=Y4-1;i>=Y3;i--){
res=(res+G(X4+1,i,C,D)*(X4+i+1)%mod*G(A,B,X4,i)%mod)%mod;
}return res;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>X1>>X2>>X3>>X4>>X5>>X6>>Y1>>Y2>>Y3>>Y4>>Y5>>Y6,init(2000000);
v1.pb({X1-1,Y1-1,1}),v1.pb({X1-1,Y2,-1}),v1.pb({X2,Y1-1,-1}),v1.pb({X2,Y2,1});
v2.pb({X6+1,Y6+1,1}),v2.pb({X5,Y6+1,-1}),v2.pb({X6+1,Y5,-1}),v2.pb({X5,Y5,1});
int res(0);
for(int i=0;i<4;i++)for(int j=0;j<4;j++)res=(res+solve(v1[i].X,v1[i].Y,v2[j].X,v2[j].Y)*v1[i].Z*v2[j].Z)%mod;
cout<<(res+mod)%mod;
}