[NOIP集训]10月20日
今天的文件夹:10月20日.zip
今天是搜索题专练。
T1:这题用搜索找规律可以,AC就别想了。搜索起来,每次枚举两种操作(push和pop),判断是否合法,递归2n次后比较出栈序列并统计总数。当然,对于极限数据这是不能通过的(一共要递归2n层,总的时间复杂度为O(22n)),因此要用数学方法。
经过数学上的推导(详情百度,这里给大家一个链接和百度百科),结果应该是第n个Catalan数,即
h(n)=n−1∑i=1h(i)∗h(n−i)=h(n−1)∗4n−2n+1=Cn2nn+1
其中h(0)=h(1)=1。
计算输出即可,注意数据不要爆了int64。
T2~T9晚上再填。。。
T10:对于不能的情况,方法很简单。我们对所有的临近湖泊的点做一次BFS,看能到达临近沙漠的哪些点,最后统计输出即可。而对于能实现的情况,我们也可以用这种方法,统计出每个临近湖泊的点如果修建蓄水池的话,可以到达的所有点。
现在,我们有了这些数据,要求出覆盖所有临近沙漠的点时,最少要修建的蓄水池个数。这看起来很像一个集合覆盖问题,然而这个问题貌似是NP难的,不可能实现这样的规模。这告诉我们,这道题一定存在一些特殊性,只是还没有被利用。
考虑样例2,我们发现,对每个最上面的点(记为a[1,i]),可以到达最后一行的点(记为a[n,j])的集合,总能构成一条连续线段。例如,a[1,1]可以到达a[n,1],a[n,2],a[1,3]可以到达a[n,2],a[n,3],a[n,4]等等。这条规律是否普遍成立,还要证明:
定理:在能满足要求,即每一个点a[n,j](1≤i≤m)都可到达的情况下,对任意点a[1,i](1≤i≤m),它可以到达的最后一行的点总是连续的一段。
证明:采用反证法,假设存在一个点(或一个区间),它左右两侧均可由同一点到达,而这个点不能。
因为所有点都能被到达,所以必有一个最上方的点可以到达这个点,这两点间的路径(记为p)肯定与a[1,i]到左右两侧的两个点的两条路径中的至少一条相交(可以分情况证明),那么我们在交点处,令a[1,i]出发的路径沿着p行进,可以到达a[n,j]而不违反任何规则。这就推出了此点可以由a[1,i]到达,发生矛盾。
综上,定理得证。因此,这些集合可以看做m条线段,要让它们覆盖另一条线段。这不就是经典的线段覆盖模型吗?我们令s[i],t[i]分别表示第i条线段的起点、终点,ans[i]表示线段1..i至少需要多少条线段来覆盖,那么
ans[i]=min
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步