首先我们只会计算的情况是,给定起点和终点,计算从起点到终点的路径条数。由于起点和终点都是不确定的,因此显然不能直接计算。
然而这道题的本质还是在考察洞察能力 而我在这方面恰巧是比较差的 。算法设计毕竟是先验科学。
我们考虑,从一个点走到一个矩形区域的方案数是多少呢?
设
F
x
,
y
F_{x,y}
F x , 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}
F x , y = ∑ i = 0 y F x − 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}
F c + 1 , d + 1 − F a , d + 1 − F c + 1 , b + F a , b 。
那么问题转化为给定起点和终点,经过中间矩形区域其中一个点的方案数。我们枚举进入和出去中间矩阵的位置,那么能被选为中转点的数目就是这两个点的曼哈顿距离,注意到坐标是可以分离的 ,因此将贡献拆开计算即可。
复杂度
O
(
n
)
O(n)
O ( n ) 。
优秀的
OIer
\text{OIer}
OIer 应该是一位优秀的数学家。
猜想,是一个
OIer
\text{OIer}
OIer 最有力的武器。
#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;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」