#题面
#题目背景
愚蠢的戴夫种了一些豌豆射手。
愚蠢的戴夫只会把豌豆射手种在一列草坪上,并且因为戴夫不懂得种植向日葵,所以他并没有足够的阳光使得这一列都放满豌豆射手。
但这些豌豆射手除了会向前喷射豌豆,还会向左右喷射豌豆,并且向左右喷射豌豆有一个飞行距离限制。
一大波僵尸即将来临,戴夫想要知道,有多少种安排豌豆射手的方案,使得没有两个豌豆射手会相互攻击。
#题目描述
现在有 个豌豆射手,要把它们放在长度为 的一列草坪上。
每一个豌豆射手都有一个攻击半径 ,如果将这个豌豆射手放在 位置,那么 将不能有其他的豌豆射手。
戴夫要把这 个豌豆射手放在长度为 的草坪上,使得它们不会相互攻击,求方案数。答案对 取模
#输入格式
第一行两个整数 ,表示有 个豌豆射手,草坪的长度为 。
第二行 个整数 ,表示每一个豌豆射手的攻击半径。
#输出格式
一行一个整数,表示合法的方案数。
#输入输出样例
样例输入 #1
4 4
1 1 1 1
样例输出 #1
24
样例输入 #2
3 47
4 8 9
样例输出 #2
28830
样例输入 #3
8 100000
21 37 23 13 32 22 9 39
样例输出 #3
923016564
#数据范围与约定
对于 的数据,,;
对于 的数据,;
对于 的数据,,,,。
#思路
设豌豆射手的顺序为 ,设 ,则当前排列的方案数为 。那么问题就转变为了对于每一个 有多少方案。
先将 升序排序,设 表示前 个点中有 个点的左右位置还可以放置豌豆射手(称为空闲点),放置后 的大小为 的方案。
初始值:,表示一开始一个点都没有,空闲点的数量也是 ,合并的长度也是 的方案。
定义「合并」:表示将一个新的点和一个空闲点相连,那么新合成的这一段又可以看成一个空闲点。有以下几种情况:
-
将当前点合并到某个空闲点的左右两边。
此时空闲点的数量不变,长度加上新的点的半径。
由于已经对 进行过排序,所以 一定是 和 中最大的那个,直接使用即可。
式子中的乘 是可以从 个空闲点中挑出一个和新的点合并,乘以 是可以放在左右两边。
-
将当前点插入到两个空闲点的中间,使左右两个空闲点合并。
此时空闲点的数量减 ,长度加上新半径乘以 ,因为往左右两边扩展,然后减去中间算重复的。
因为这 个空闲点具体位置在哪都是不确定的,选取出两个点左右关系也是不确定的,所以乘 而不是除 。
-
单独成为一个空闲点。
此时空闲点的数量加 ,长度加 。
时间复杂度为 。
#代码
1 |
|