| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 1585 例题1 Amount of Degrees(Ural 1057 LOJ10163) 进制转换纯枚举从40分到60分 数位DP100分 初次使用string -> 正文阅读 |
|
[数据结构与算法]1585 例题1 Amount of Degrees(Ural 1057 LOJ10163) 进制转换纯枚举从40分到60分 数位DP100分 初次使用string |
看完题目,感觉就是一个进制转换。 样例数据如下:
该题有个极端的测试数据:
很明显,AC的解法,一定是成片的计算数量。 目前能怎么办?从初级的算法入手,慢慢改进,看能到什么程度。 1.进制转换,纯枚举,输出符合的数量. 样例通过,提交40分 ybt 未通过
LOJ ?40分代码如下:
超时可以理解,有测试点错误,不可接受,想不通。 突然想到一组测试数据:
然而上述代码对应的输出是5 很显然5=2*3^0+1*3^1等无效数据也被统计了。 ybt 未通过
LOJ ?60分代码如下:
2.数位DP?????? 由于所求的幂互不相等,符合条件的数写成B进制一定只由0和1组成。 因此我们只考虑B=2的情况。 此处区间满足区间减法,即count(X,Y)=count(0,Y)-count(0,X-1) 因此我们唯一需要求的就是,给定n,求出所有不超过n的正整数中,其二进制表示恰好含有K个"1"的有多少。 这里,我使用一棵完全二叉树来代表一个区间内的数。 例如图中高度为4的完全二叉树就可以代表所有长度为4的二进制数。 (左枝是0,右枝是1,有点像哈夫曼编码。) 其范围为[0,2^4-1] 每个叶子就代表了一个数。 假设K=3 ,n=13,其二进制为1101。
为了方便起见,树的根(
人为引入
)用
0
表示。这样,这棵高度为
4
的完全二叉树就可以表示所有
4
位二进制数(
0..2^
4
-1
),每一个叶子节点代表一个数。其中,红色路径表示
n
。所有小于
n
的
数组成了三棵子树,分别用蓝色、绿色、紫色表示。因此,统计小于
13
的数,就只需统计
这三棵完整的完全二叉树:统计蓝子树内含
3
个
1
的数的个数、统计绿子树内含
2
个
1
的数
的个数(因为从根到此处的路径上已经有
1
个
1
),以及统计紫子树内含
1
个
1
的数的个数。
注意到,只要是高度相同的子树统计结果一定相同。而需要统计的子树都是“右转”时遇到
的(
请注意:统计的全是左子树
)。当然,我们不能忘记统计
n
本身。实际上,在算法最初时将
n
自加
1
,可以避免讨论
n
本身,但是需要注意防止上溢。
很容易递推求出这个问题: 设f[h,s]表示在高度为h(h>=1,因根节点0是人为引入)的完全二叉树包含的数中(范围是[0,2^h-1]),二进制中恰含s个1的数有多少。(注意s<=h,因具体到某个数,是从根节点走到叶节点经历的01) f[h,s]? =? f[h-1,s] (左子树中的个数)?+? f[h-1,s-1](右子树中的个数) (注:f[h,s]根是0 f[h-1,s]左子树的根是0,故除左子树根节点0外,还需s个1. f[h-1,s-1]右子树的根是1,故除右子树根节点1外,还需s-1个1.) 剩下的问题就是,如何将任意进制问题转化为二进制问题。 (若左起有大于1的数位,下面转换对右边界Y没有问题,转换只是将不大于Y的符合题意的数找出,因Y本身不符合题意,故右边界没有少计数,也没有多计数。) (若左起有大于1的数位,下面转换对左边界X没有问题,转换只是将不大于X的符合题意的数找出,因X本身不符合题意,故左边界没有少计数,也没有多计数。) (思维难点)只需贪心将n的B进制表示转化为只含01:找到n的左起(左是高位)第一位大于1的数位,将它以及它右边所有数位赋为1(即找到最接近n的符合题意的数)。 递推求f的时间复杂度为O(log^2(n)),每次询问的时间复杂度为O(log(n)),因此总时间复杂度为O(log^2(n))。 问题得到完美解决! 实际上,我们也可以只用“位”的思想来考虑这个问题,而不使用树的思想。 我们每次找到n的"1"数位,将它赋为0,则其右面的数位可任取0、1。 可根据组合数算出满足题意的数的个数。 穷举所有“1”数位,计算组合数,即可完成询问。 事实上,f的递推公式正是组合数公式! 与树的思想异曲同工! ?使用高度为h的完全B叉树表示所有长度为h的B进制数,思考起来更加直观,在处理较复杂问题时优点明显。 当然,最终程序我们并不真正建树,它的作用只是帮助我们思考。 无论从树结构考虑还是从数位的角度考虑,基本思想都是: ?逐位确定 ybt 通过
LOJ
该题习得什么? 第一次对数位DP有了印象,心心念的二进制位操作出现了。 在统计ans过程中,细节较多,该题若作为试题,100分的代码初次编写时很难完成的。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 11:29:47- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |