【luogu P8340】山河重整(容斥)(DP)
山河重整
题目链接:luogu P8340
题目大意
有 1~n 这 n 个数,问你有多少种选的方案,使得 1~n 中的每个数都可以表示为你选的其中一些数的和。
思路
考虑怎么才会满足条件,我们考虑从小的数开始组。
那 肯定要有 , 的话也是,那我们看 以及以上 ,那你会发现你肯定要用 的来拼,那首先由必要条件是 的部分的和要 ,然后其实你会发现它是必要的 。
因为你 的都可以被凑出来,找到最小的 使得 的和 ,那设这个值是 ,那 ,那 ,那这个也可以被表示出来。
那你用 的集合减去 的集合不就得到 了吗。
于是我们就变成数有多少个集合使得对于所有的 都满足集合中 的值的和 。
发现这个是每个位置都要满足不好统计,考虑找不合法的:存在一个位置 使得 的值的和 。
那接着就有一个比较显然的东西就是要满足这个一定会有 的值恰好为 !
(然后接着 这个位置没有值)
那我们是不是可以根据这个来弄呢?
设 为 的部分选一些恰好为 ,且前面过程全部满足合法条件的。
那这里又要合法条件了,那也没关系,我们再看怎么容斥掉嘛。
那先看不管合不合法的,先有多少种情况。
那就是一个整数划分(划分成的数互补相同),然后你会发现拆出来数的个数是 级别的。
()
这个表示的就是 的一个拆分。
那我们你这里是一列一列的加,我们能不能一行一行的加呢?毕竟行的长度是 级别。
那其实是可以的,那我们看看有什么特别的性质:
会发现如果一行有 的长度,那一定要有 的长度。
然后同一个长度没有数量限制,那不就是一个有上面这个特别限制的完全背包吗!
然后至于这个限制怎么弄,我们就从大到小来枚举放行的长度,然后这样我们可以强制要么新开一个放,要么就一定要强制在之前的基础上继续放,这样就可以满足上面的条件了。
(具体实现可以看看代码,就是强制至少选一个,然后再完全背包)
那接下来就只剩下一个问题了,就是怎么减去不合法的方案。
那不难看出不合法其实就是你这里不满足的一部分,那感觉就可以 DP。
那我们再看看不合法具体会怎样:
首先一个位置 满足 的和为 ,然后 没有,然后后面 中会选一些跟 加起来得到 。
那这里就有一个条件,就是后面是一定要选的,那选最小的值就是 ,那有可能能凑到 就至少需要 。
那后面就是 个里面从 取得。
(后面也是拆)
拆像之前一样拆,然后那每个数多放进去就额外有 的贡献。
所以你每个位置初始放就是不一样的了:
那你得先枚举 ,然后你重新看是什么代表着放进去数的数量,会发现其实就是 ,那你初始化的位置就是 ,那放的值就是 。
然后也是完全背包就可以。
然后又有一个问题,你求 需要用到 ,也就是要前面的值啊。
那怎么搞呢?(其实会发现这个东西很分治)
然后你还发现还有一个性质就是我们刚刚说的 ,那每次只会用到前面的一半当做 。
那我们根本不用分治,直接倍增就好,求出 ,然后用这个来求 的答案即可。
代码
__EOF__

本文链接:https://www.cnblogs.com/Sakura-TJH/p/luogu_P8340.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现