题目链接
题目类型:容斥原理 + Lucas求组合数
题目来源:2016 Multi-University Training Contest 6
题目分析
题目大意
$n*m$的棋盘上,一个棋子要从$(1, 1)$点走到$(n, m)$点,棋子只能向右下的方向移动,类似“马走日”的方法移动,现在棋盘上有一些障碍,棋子无法走到这些有障碍物的地方,问你有多少种方法,从$(1, 1)$走到 $(n, n)$
解析
一开始想的太简单了,觉得只要找到障碍物的点,然后去掉该点的数字即可,在特殊情况下是这样的,但是如果障碍物a影响了某个点b的方案数,然后又在这个b点放置障碍物要怎么办呢?肯定没有这么简单,需要把大情况中的小情况考虑清楚,这样就又变成了一道容斥的问题。将$m$个障碍物排序,然后依次处理,算上一个障碍物对当前障碍物的影响,求出来到达当前障碍物的方案数量。
别人家的题解——HDU 5794 A Simple Chess (容斥+DP+Lucas)
问题一:如何计算路线数
如果不存在任何障碍,从点(x1,y1)到点(x2,y2):
①. 不能到达:由于走的是”L”型路线(类似象棋的马),所以有可能到不了.
每走一步实际上是移动了三个单位(包括上下方向),而起点到终点共有(x2-x1) + (y2-y1)个单位.
所以能走到的充分必要条件是:((x2-x1)+(y2-y1)) % 3 == 0 ; 且终点在起点的左下方(x2>x1 && y2>y1).
②. 如果能到达:走的步数是 step = (x2+y2-x1-y1) / 3.
走法有 “L”型{(x,y)=>(x+2,y+1)} 和 “倒L”型{(x,y)=>(x+1,y+2)} 两种.
无论怎么走都至少会在上下两方向上都减1. 所以上下两方向各剩下 s1=x2-x1-step 和 s2=y2-y1-step 个单位.
再用”L”型和”倒L”型去分配这剩下的单位. 即 C(s1+s2, s1) 或 C(s1+s2, s2).
③. 由于坐标范围较大,而取模的p=110119较小且为质数.
所以这里用lucas公式来求组合数.
(一般的:数较小且mod较大时用逆元求组合数,数较大且mod较小时用lucas求组合数)
(由于上述公式中s1 s2有可能为负数,所以lucas里面一定要对负数组合数作特判)(论完美模版的重要性).
问题二:如何考虑障碍物
容斥 + DP:坐标范围较大,只能对障碍位置进行dp:
dp[i]: 从(1,1)到障碍i且不经过其他障碍的路线数.
转移方程:
dp[i] = (起点到障碍i的路线) - Σ(dp[j] * (障碍j到障碍i的路线))
(其中j为位于障碍i左上方的障碍,即j可以通过合法路径到达i. 因此处理时先对障碍坐标排序).
代码
1 |
|