[AGC018E] Sightseeing Plan
tag:组合计数
计数好题(
题意
给定三个矩形,保证顺序为从左下到右上,且不相交。三个矩形中各取一个点,\(S,P,T\),计算从 \(S\) 经过 \(P\) 到 \(T\) 的方案数,求所有选取方法的方案数之和。
一步一步考虑。
点到点
从 \((x_1,y_1)\) 到 \((x_2,y_2)\)。一共走 \(x_2-x_1+y_2-y_1\) 步,其中有 \(x_2-x_1\) 步是横着走的,方案为 \(\dbinom{x_2-x_1+y_2-y_1}{x_2-x_1}\)
点到矩形
\((x_1,y_1)\to(x_2,y_2,x_3,y_3)\)
设 \(f(x,y)\) 为 \((x_1,y_1)\to(x,y)\) 的方案数。则有
前者是枚举最后一步横着走的时间,后者是枚举最后一步竖着走的时间。
然后就是四个组合数加减。
矩形到矩形
\((x_1,y_1,x_2,y_2)\to(x_3,y_3,x_4,y_4)\)
枚举起点,则答案为第一个矩形到第二个矩形的四个关键点的路径数之和。也就是说,第二个矩形的一个关键点的贡献为,第一个矩形到这个点的路径数之和,和“点到矩形”是等价的。
所以答案为两个矩形的四个关键点之间16条路径的加减。
不过注意“矩形到点”,关键点为 \((x_2,y_2,1)(x_1-1,y_2,-1)(x_2,y_1-1,-1)(x_1-1,y_1-1,1)\),可以理解为翻转了一下。
到此为止,如果不考虑 \(P\),原问题就转化为了求 \(16\) 条路径的方案数。
路径经过矩形
\(s\to(x_1,y_1,x_2,y_2)\to t\)
可以枚举进入矩形的那条边,做到不重不漏。
此题
由于本题可以选取 \(P\),所以经过矩形的一条路径的贡献为,这条路径在矩形内部部分的 \(len\)。而 \(len=x_2-x_1+y_2-y_1\),所以实际上进入点和退出点的贡献是可以分开计算的。
进入点的贡献系数为 \(-(x+y)\),退出点的贡献为 \((x,y)\)。于是分别枚举进入点和退出点就行了。
inline int calc(point s, point t){
int res = 0;
for(register int i=x[3]; i<=x[4]; i++)
res = dec(res,1ll*calc(s.x,s.y,i,y[3]-1)*calc(i,y[3],t.x,t.y)%MOD*(i+y[3])%MOD),
res = (res+1ll*calc(s.x,s.y,i,y[4])*calc(i,y[4]+1,t.x,t.y)%MOD*(i+y[4]+1))%MOD;
for(register int i=y[3]; i<=y[4]; i++)
res = dec(res,1ll*calc(s.x,s.y,x[3]-1,i)*calc(x[3],i,t.x,t.y)%MOD*(x[3]+i)%MOD),
res = (res+1ll*calc(s.x,s.y,x[4],i)*calc(x[4]+1,i,t.x,t.y)%MOD*(x[4]+1+i))%MOD;
if(s.opt^t.opt) return neg(res);
return res;
}