首页 > 其他分享 >[NOI2022] 移除石子

[NOI2022] 移除石子

时间:2024-01-31 15:25:48浏览次数:26  
标签:le 线段 石子 样例 NOI2022 移除 dp

[NOI2022] 移除石子

题目描述

你正在玩一个名为“移除石子”的小游戏。

有 \(n\) 堆石子排成一行,第 \(i\) 堆有 \(a_i\) 枚,你的任务是通过如下的操作将所有石子移除:

  • 操作一:选择一堆石子,将其中的至少 \(2\) 枚石子移除;
  • 操作二:选择一个连续的编号区间 \([l, r]\)(\(1 \le l \le r \le n\))并满足 \(r - l \ge 2\),将其中的每一堆石子都恰好移除 \(1\) 枚。

你可以采用任意顺序执行任意多次上述两种操作,直到无法再执行操作为止。若最后你能将所有石子全部移除则胜利。

你或许已经开始计算起了诸如“有多少种本质不同的操作方式”的问题,但实际玩起来你却发现自己总是在输。因此,你打算玩个小花招:在游戏开始时,你在手里偷偷藏有 \(k\) 枚石子,在执行所有操作之前你可以且必须将这些石子放入某一堆或某几堆石子中。你期望这会提高自己的胜率,但也清楚这可能会使自己输掉原本可能胜利的游戏。

现在,你可以自由选择一个初始局面进行游戏,具体而言,每个 \(a_i\) 可以选择 \([l_i, r_i]\) 范围内的任意整数。你希望计算出,在多少种初始局面下,自己存在至少一种获胜的方案。由于答案很大,你只需要输出其对 \(({10}^9 + 7)\) 取模的结果。两个初始局面不同,当且仅当存在至少一个 \(\boldsymbol{1 \le i \le n}\) 使得两者的 \(\boldsymbol{a_i}\) 不相等,注意这里的“初始局面”指的是你放入 \(\boldsymbol{k}\) 枚石子之前的局面。

输入格式

本题有多组测试数据。 第一行一个正整数 \(T\) 表示测试数据组数,接下来依次给出每组测试数据。

对于每组测试数据,第一行两个整数 \(n, k\),分别表示石子堆数和加入的石子个数,接下来 \(n\) 行,每行两个非负整数 \(l_i, r_i\) 表示每堆石子初始石子数的范围。

输出格式

对于每组数据输出一行一个整数,表示可能获胜的局面数对\(({10}^9 + 7)\) 取模的结果。

样例 #1

样例输入 #1

1
4 1
0 1
0 1
0 1
0 1

样例输出 #1

14

提示

【样例解释 #1】

共有 \(2^4 = 16\) 种可能的初始局面,可以证明除了 \((0 \ 0 \ 0 \ 0)\) 和 \((1 \ 0 \ 0 \ 1)\) 这两种初始局面无法获胜以外,其余初始局面均存在获胜方案。例如,初始局面为 \((1 \ 0 \ 1 \ 0)\) 时,你可以将手中的 \(1\) 枚石子放入第 \(2\) 堆石子,使局面变为 \((1 \ 1 \ 1 \ 0)\),再对区间 \([1, 3]\) 使用一次操作二即可。


【样例 #2】

见附件中的 stone/stone2.instone/stone2.ans


【样例 #3】

见附件中的 stone/stone3.instone/stone3.ans


【样例 #4】

见附件中的 stone/stone4.instone/stone4.ans


【数据范围】

对于 \(100 \%\) 的数据,保证 \(T \le 10\),\(3 \le n \le 1000\),\(0 \le l_i \le r_i \le {10}^9\),\(0 \le k \le 100\)。

测试点编号 \(n \le\) \(k \le\) 特殊条件
\(1 \sim 3\) \(5\) \(2\) \(r_i \le 5\)
\(4 \sim 5\) \(1000\) \(0\) \(l_i = r_i\)
\(6 \sim 8\) \(1000\) \(100\) \(l_i = r_i\)
\(9 \sim 11\) \(1000\) \(0\)
\(12 \sim 13\) \(1000\) \(2\)
\(14 \sim 15\) \(1000\) \(100\) \(r_i \le 10\)
\(16 \sim 20\) \(1000\) \(100\)

非常厉害的一道题。
先考虑判定

  • 用任意长度的线段等价于用3,4,5的线段。
  • 一个端点同时伸出长度为4,5的线段等价于一次操作2后在他的下一个端点延伸出长度为3,4的线段。
  • 两个相同的线段可以用操作2解决。
  • 推论:一个端点最多成为两个线段的左端点。

有了这个东西就可以进行 k=0 情况的 dp 了。定义 \(dp_{i,j,c}\) 表示以 \(i-2\) 为左端点的线段有 \(j\) 个,\(i-1\) 为左端点的线段有 \(c\) 个是否有可能。转移的时候枚举 \(i-2\) 处有多少个线段延伸到了 \(i-1\) 处即可。

考虑 \(k\ne 0\),发现在大多情况中, \(k\) 是满足的话,\(k+1\) 也是满足的。只有两种特例

  • 序列为三个 1,\(k=1\)
  • 序列为全0,\(k=1\)

特判掉这两种,改变定义为 \(dp_{i,j,c}\) 至少要增加多少个点才可能合法。答案对 101 取 min。

现在考虑原题,考虑 dp 套 dp。定义 \(f_{i,S}\) 为前 \(i\) 个数,dp数组的状态为 S 的时候,有多少种方案。打表发现,可能的 dp 数组的状态是8758种的。写一个搜索搜出所有状态,然后 dp 即可。

标签:le,线段,石子,样例,NOI2022,移除,dp
From: https://www.cnblogs.com/mekoszc/p/17999306

相关文章

  • 代码随想录算法训练营第三天 |203.移除链表元素 , 707.设计链表,206.反转链表
    206.反转链表 已解答简单 相关标签相关企业 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例1:输入:head=[1,2,3,4,5]输出:[5,4,3,2,1]示例2:输入:head=[1,2]输出:[2,1]示例3:输入:head=[]输出:[] 提示:链......
  • 代码随想录算法训练营第三天| 203.移除链表元素,707.设计链表 ,206.反转链表
    203.移除链表元素给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val==val 的节点,并返回 新的头节点 。题目链接:203.移除链表元素-力扣(LeetCode)注意c++中NULL和nullptr的区别。应该用nullptr来表示空指针。/***Definitionforsingly......
  • 【VMware vSAN】使用命令行从vSAN集群中移除ESXi主机并加入到新的vSAN集群。
    说明本文只是陈述了一种方法,不必评判谁对谁错谁好谁坏,选择适合自己的即可。 环境站点名称vCenter版本vSAN集群集群主机主机版本磁盘组vcsa67.lab.comvCenter6.7U3clusteresxi-b1.lab.comesxi-b2.lab.comesxi-b3.lab.comesxi-b4.lab.comESXi6.7U3......
  • 代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素。
    704.二分查找题目链接:https://leetcode.cn/problems/binary-search/文章讲解:https://programmercarl.com/0704.二分查找.html简单的二分查找法,核心是认识区间的意义,注意以下几点:middle=low+(low+high)/2;这种写法可以防止溢出。注意low和high的循环条件判断,如果是左闭右闭......
  • remove 移除数据
    //云端代码constdb=uniCloud.database()exports.main=async(event,context)=>{constcollection=db.collection(event.name)constdocList=awaitcollection.where(event.data).get()if(!docList.data||docList.data.length===0){......
  • leedcode 移除元素
    自己写的:classSolution:#122334defremoveElement(self,nums,val):numms_len=len(nums)ifnumms_len==0:returnnumms_leni=0whilei<numms_len:ifnums[i]==val:......
  • 【LeetCode】27. 移除元素
    题目:27.移除元素解题思路给定一个数组,以及一个需要删除的值;要求在O(1)的空间复杂度中完成可考虑采用快慢指针的方式,left用于记录当前需要进行替换的元素,right指针用于遍历整个数组当right指针所指的值是待删除元素时,那么right右移,left不动即可若不是,那么将right......
  • 代码随想录算法训练营第一天| LeetCode704 二分查找,LeetCode35,LeetCode34,leetcode27.
    LeetCode704题目链接:704.二分查找-力扣(LeetCode)第一时间的想法:简单来说,二分法给我的印象就是想一条绳子上打很多的结,每次对折正好是一个结点,我们需要找到想要的结点比如(a)代码思路就是不断对折一直到绳子两端重合中间没有结点,最后剩下的就是要找的结点a了。......
  • [FAQ] Docker查询出所有的停止容器并移除
     $ dockerrm`dockercontainerls-a--filter"status=exited"|awk'{print$1}'|sed'1,1d'|xargs` Ref:phvia/dkcRef:[Shell]字符截取命令:cut,printf,awk,sedRef:使用nodejs的puppeteer库使用完关闭后,linux上面有很多chrome进程Link:https......
  • #yyds干货盘点# LeetCode程序员面试金典:移除盒子
    题目给出一些不同颜色的盒子boxes,盒子的颜色由不同的正数表示。你将经过若干轮操作去去掉盒子,直到所有的盒子都去掉为止。每一轮你可以移除具有相同颜色的连续k个盒子(k>=1),这样一轮之后你将得到k*k个积分。返回你能获得的最大积分和。 示例1:输入:boxes=[1,3,2,......