求给出第 K (0 < K < 109) 个 N (0 < N < 44) 位二进制数,该二进制数不得有相邻的“1”。

这道题要求给出第 K (0 < K < 109) 个 N (0 < N < 44) 位二进制数,该二进制数不得有相邻的“1”。由于时间限制是 0.5 秒,肯定不能使用蛮力搜索从 1 列举到 K。

我们以 N = 5 来分析看看有没有什么规律。如左图所示,我们发现该二进制数最左边的“1”开始在第几个数之后出现是很规律的,如下所示(左图中红色粗框中的数):

1, 2, 3, 5, 8, 13, ...

也就是说,后项等于前二项之和。这不正是扔掉第一项后的斐波那契 ( Fibonacci ) 数列吗?

于是,程序在第 35 到 42 行的 GetFibonacci() 方法中计算出该数列。然后在第 22 到 33 的 GetBinarys() 方法中计算出第 K 个满足条件的二进制数。该方法在第 26 到 31 行的循环中从高位到低位设定“1”(如左图中红色细框所示)。

请注意,左图中两块阴影部分的内容是相同的,都代表了 N = 3 的情况。也就是说,N = 5 的最低三位是在重复 N = 3 的情况。并且由于该二进制数不得有相邻的“1”,所以在程序第 28 行使用 i - 2 而不是 i - 1 作为第 2 个参数调用 Seek() 方法,然后在第 30 行将该二进制数的第 i 位设为“1”。最后在第 26 行 k -= fib[i],以进入下一轮循环,直到 k 降低到 1 而结束循环。

本程序的算法应该是最优的,其时间复杂度为 O(N)。本程序的运行时间是 0.078 秒,其 C++ 版本程序的运行时间是 0.001 秒。

我们知道,斐波那契 ( Fibonacci ) 数列定义如下:

F1 = 1, F2 = 1, Fn = Fn-1 + Fn-2 (n > 2)

她的前几项如下:

DP关键在于找到状态转移方程,而找方程关键在于找状态。我们从限制条件开始构造状态。以位数N和K构造是不现实的,数据量太多,我们可以位数为N的二进制数的个数作为状态,这样如果第i位填0则f[i] = f[i-1] 如果第i位填1则第i-1位只能填0,此时f[i] = f[i-2]总之,f[i] = f[i-1] + f[i-2];这个就是传说中的转移方程。

然后考虑第K个的问题,因为开头为0的数必然排在开头为1的数的前面。也就是位数为N的数共有f[i]个,其中前面的是以0开头的f[i-1]个,后面是以1开头的f[i-2]个,所以如果K小于等于f[i-1]则其第i位必然为0,然后去考虑第i-1位,此时K不变;否则其第i位必然为1第i-1位必然为0,然后去考虑第i-2位,此时K= K-f[i-1]。

K= K-f[i-1]?
一个串,把右端的叫低位,叫第1位,左端的叫高位,叫第43位,(最多这么多位)
dp[n][0],表示第n位放0,到第1位,一共能产生多少个串
dp[n][1],表示第n位放1,到第1位,一共能产生多少个串

如果按照字典序来排,肯定第n位放0的话,字典序比放1的要小(无需考虑后面的)
现在要找第m个排序,看看第n位放0的话,能产生多少个排列,如果放0,产生的排序数都不够m大,那么这一位肯定是放1的,放了1,就应该从m-dp[n][0]重新考虑了,因为相当于你排除了放0的所有情况

求dp数组是一个从低位向高位编码的过程
求第m个排列,是一个从高位向低位解码的过程,解码就是从高位到低位,一位一位地确定到底是放1还是放0

求给出第 K个 N位二进制数,该二进制数不得有相邻的“1”的更多相关文章

  1. 已知w是一个大于10但不大于1000000的无符号整数,若w是n(n≥2)位的整数,则求出w的后n-1位的数。

    描述 已知w是一个大于10但不大于1000000的无符号整数,若w是n(n≥2)位的整数,则求出w的后n-1位的数.   输入 第一行为M,表示测试数据组数.接下来M行,每行包含一个测试数据. 输出 ...

  2. ACM1229_还是A+B(求A的第K位的数公式:A%((int)(pow(10,K)))

    #include<stdio.h> #include<math.h> int main() { int A,k,B,sum,c,d; while(scanf("%d% ...

  3. 海量数据中找出前k大数(topk问题)

    海量数据中找出前k大数(topk问题) 前两天面试3面学长问我的这个问题(想说TEG的3个面试学长都是好和蔼,希望能完成最后一面,各方面原因造成我无比想去鹅场的心已经按捺不住了),这个问题还是建立最小 ...

  4. POJ1741--Tree (树的点分治) 求树上距离小于等于k的点对数

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 12276   Accepted: 3886 Description ...

  5. poj 3261 求可重叠的k次最长重复子串

    题意:求可重叠的k次最长重复子串的长度 链接:点我 和poj1743差不多 #include<cstdio> #include<iostream> #include<al ...

  6. Gym 101064 D Black Hills golden jewels 【二分套二分/给定一个序列,从序列中任意取两个数形成一个和,两个数不可相同,要求求出第k小的组合】

    D. Black Hills golden jewels time limit per test 2 seconds memory limit per test 256 megabytes input ...

  7. OpenJudge计算概论-找出第k大的数

    /*================================================ 找出第k大的数 总时间限制: 1000ms 内存限制: 1000kB 描述 用户输入N和K,然后接 ...

  8. 求x!在k进制下后缀零的个数(洛谷月赛T1)

    求x!在k进制下后缀和的个数 20分:     求十进制下的x!后缀和的个数 40分: 高精求阶乘,直接模拟过程 (我不管反正我不打,本蒟蒻最讨厌高精了) 60分     利用一个定理(网上有求x!在 ...

  9. 用PL0语言求Fibonacci数列前m个中偶数位的数

    程序说明:求Fibonacci数列前m个中偶数位的数: 这是编译原理作业,本打算写 求Fibonacci数列前m个数:写了半天,不会写,就放弃了: 程序代码如下: var n1,n2,m,i; pro ...

随机推荐

  1. Hibernate关联映射之_一对多

    domain: package org.zln.hibernate.domain; import java.util.Set; /** * 部门Domain对象 * Created by sherry ...

  2. JVM GC Q&A(补充ing)

    1.如果一个对象没有与其相连的GC ROOT,一定会被回收吗? 这个对象并非是非死不可的,这时他只是处于死缓阶段,要真正宣告一个对象的死亡,至少要经历两次标记过程:如果对象在进行可达性分析后发现并没有 ...

  3. 某ISP的流氓行径 劫持用户HTTP请求插入js代码

    最近公司搞的项目有用户反应点击任意链接后偶尔会跳到一个“莫名奇妙”的网站………… 喏,就是这个咯.

  4. taotao前台页面显示登录用户名的处理

    思路: 在每个页面上都引入一个 jsp,这个 jsp 可以是页面的头 head 或者脚 footer.jsp 然后在这个 jsp 中引入 一个 js,这个 js 中 有个 随页面加载 而执行的 方法, ...

  5. Spring事务只对运行时异常回滚

    我们在使用Spring时候一般都知道事务在遇到异常的时候会回滚,岂不知Spring的事务默认只有在发生运行时异常即:RunTimeException时才会发生事务,如果一个方法抛出Exception或 ...

  6. 解决导出为Excel时文件名乱码的问题。

    以前代码:public static void htmlToExcel(HttpContext context, string title, string html, string fileCss = ...

  7. CMDB资产管理系统开发【day26】:02-数据写入待存区

    一.资产自动回报数据及个更新流程图 二.表结构注释(NewAssetApprovalZone) class NewAssetApprovalZone(models.Model): "&quo ...

  8. 使用Spring AOP实现读写分离(MySql实现主从复制)

    1.  背景 我们一般应用对数据库而言都是“读多写少”,也就说对数据库读取数据的压力比较大,有一个思路就是说采用数据库集群的方案,其中一个是主库,负责写入数据,我们称之为:写库: 其它都是从库,负责读 ...

  9. VC关于置顶窗口的方法小结

    转摘自:http://blog.csdn.net/wirror800/article/details/4002381 将窗体置顶的方法有: //将窗体置顶的API函数 ::SetWindowPos(m ...

  10. html中offsetTop、clientTop、scrollTop、offsetTop各属性介绍(转载)

    HTML精确定位:scrollLeft,scrollWidth,clientWidth,offsetWidth scrollHeight: 获取对象的滚动高度. scrollLeft: 设置或获取位于 ...