热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

[BZOJ]2734[HNOI2012]集合选数状压DP思路神题

2734:[HNOI2012]集合选数TimeLimit:10SecMemoryLimit:128MBSubmit:1475Solved:876[Submit][Status][D

2734: [HNOI2012]集合选数

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1475  Solved: 876
[Submit][Status][Discuss]

Description


《集合论与图论》这门课程有一道作业题,要求同学们求出{1, 2, 3, 4, 5}的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x 不能在该子集中。同学们不喜欢这种具有枚举性 质的题目,于是把它变成了以下问题:对于任意一个正整数 n≤100000,如何求出{1, 2,..., n} 的满足上述约束条件的子集的个数(只需输出对 1,000,000,001 取模的结果),现在这个问题就 交给你了。 
 



Input


 只有一行,其中有一个正整数 n,30%的数据满足 n≤20。 
 



Output



 仅包含一个正整数,表示{1, 2,..., n}有多少个满足上述约束条件 的子集。 
 



Sample Input



4


Sample Output


8

【样例解释】

有8 个集合满足要求,分别是空集,{1},{1,4},{2},{2,3},{3},{3,4},{4}。


HINT




Source


day2



[Submit][Status][Discuss]



HOME Back

  一开始有一个朴素的思路就是dp[i][0/1]表示当前选还是不选的方案数, 然后减去dp[i/2][1]和dp[i/3][1]的, 发现可能会删重就需要记录一些其他的东西.... 发现处理不好gg. 于是往根号方面的复杂度去想也没有什么卵用. 看了一下30%的数据感觉暴力状压可过. 然后实在想不出来, orz了题解.

  解题思路真的有点神... 总结一下思路. 我们可以看到题目中只有2x, 3x这样的限制可以产生一点疑惑:为什么不能再是3x, 4x... 而是只有两个限制? 原来我认为无非就是一种可能:如果是dp的话dp状态会减少. 但是做了一下发现很难去除重复的情况, 选择gg. 那还有什么可能呢? 实际上在某些序列上的数据结构问题我们会发现可以将限制问题转化为几维的限制, 比如BZOJ3489, 可以化成三维限制关系kd-tree水过(虽然我写的树套树...). 那么这道题同理, 只给出了两位限制我们就往两维想. 把2的倍数设为一维, 3的倍数设为一维. 那么比如说我们可以得到这么一个矩阵(二维平面).

1 3 9 27 81....

2 6 18 54 162...

4 12 36 108 324...

  横着3倍关系, 竖着2倍关系. 我们会发现题目中要求的限制就是不能选相邻的数!很容易发现矩阵横(列)不超过11, 竖(行)不超过17, 那么一个很naive的状压就完成了. 我们同时会发现这个矩阵没有5, 7... 5的倍数, 7的倍数,没关系我们可以再构建出形如这样的矩阵:

5 15 45...

10 30 90...
20 60 120...

  这样每个矩阵状压得出的答案相乘就是结果. 这相当于从不同的矩阵里选数, 因为每个矩阵数字不重复, 显然可以运用乘法原理. 关于时间复杂度我也不会证明... 可以感性的想虽然有多个矩阵会不可过, 但实际上我们知道不是2的倍数又不是3的倍数就会被作为一个矩阵的左上角. 这样的数虽然也不少但是当数变大的时候这个矩阵也会迅速的变小(因为横着乘2次幂, 竖着乘3次幂), 状压状态数会迅速变的非常少, 所以说感觉可过QAQ... 测了极限数据快的飞起. 这样的复杂度如果较难分析实际上可以通过打表算来看是不是可过.

  所以总而言之, dp中题目限制屈指可数的话(因为越高维空间时间都开销inf啊), 除了往状态数, 枚举两方面想, 实际上还可以往维度方面想, 构造图形来dp. 这道题如果是2x,3x, 5x不可以的话, 按照之前的想法不难分析这就会是一个立方体.

#include
using namespace std;
const int mod = 1e9 + 1;
int n, tmp, ans;
bool mark[1 <<18];
int pw[19], line[19], f[19][1 <<13], a[19][13];
inline int calc(const int &x) {a[1][1] &#61; x;register int i, j;for (i &#61; 1; ; &#43;&#43; i) {if (i ^ 1) {a[i][1] &#61; a[i - 1][1] <<1;//if (a[i][1] > n) {tmp &#61; i - 1;break;}}mark[a[i][1]] &#61; true;for (j &#61; 2; ; &#43;&#43; j) {a[i][j] &#61; (a[i][j - 1] <<1) &#43; a[i][j - 1];if (a[i][j] > n) {line[i] &#61; j - 1;break;}mark[a[i][j]] &#61; 1;}}for (i &#61; 0; i <&#61; tmp; &#43;&#43; i)for (j &#61; 0; j > 1)))for (int k &#61; 0; k }
int main() {register int i;ans &#61; pw[0] &#61; 1;scanf("%d", &n);for (i &#61; 1; i <19; &#43;&#43; i)pw[i] &#61; pw[i - 1] <<1;for (i &#61; 1; i <&#61; n; &#43;&#43; i)if (!mark[i]) ans &#61; 1ll * ans * calc(i) % mod;printf("%d\n", ans);
}





推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • Linux环境变量函数getenv、putenv、setenv和unsetenv详解
    本文详细解释了Linux中的环境变量函数getenv、putenv、setenv和unsetenv的用法和功能。通过使用这些函数,可以获取、设置和删除环境变量的值。同时给出了相应的函数原型、参数说明和返回值。通过示例代码演示了如何使用getenv函数获取环境变量的值,并打印出来。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了最长上升子序列问题的一个变种解法,通过记录拐点的位置,将问题拆分为左右两个LIS问题。详细讲解了算法的实现过程,并给出了相应的代码。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
author-avatar
kaxiaoliog_334
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有