求给出第 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. BZOJ2118 墨墨的等式 【最短路】

    题目链接 BZOJ2118 题解 orz竟然是最短路 我们去\(0\)后取出最小的\(a[i]\),记为\(p\),然后考虑模\(p\)下的\(B\) 一个数\(i\)能被凑出,那么\(i + p\) ...

  2. 【ZJ选讲·钻石游戏】

    N×M的棋盘(M,N<=500)中,每个格子有一个颜色(颜色数1~9) P次操作(P<=1000),每次给出两个相邻的位置(保证颜色不同,两个格子有一条公共边),把这两个格子交换. 定 ...

  3. 如何用setInterval调用类的方法

    setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式.setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭.由 se ...

  4. 几个JavaScript的浏览器差异处理问题

    JQuery确实是个很好用的库,你可以不用考虑很多细节方面的事情.但很作为一个web前端,处理和了解浏览器差异一个重要问题.下面将介绍一些总结,先介绍没有使用js库的情况. 1. setAttribu ...

  5. bootstrap、angularJS、nodeJs、reactJs视频教程

    bootstrap.angularJS.nodeJs.reactJs视频教程 发布时间:『 2017-06-25 19:50』  博客类别:资源下载  阅读(74) 评论(0) 智能社与达内哪个好?说 ...

  6. [hdu 3949]线性基+高斯消元

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3949 一开始给做出来的线性基wa了很久,最后加了一步高斯消元就过了. 之所以可以这样做,证明如下. 首 ...

  7. NOIP2003 神经网络(bfs)

    NOIP2003 神经网络 题目背景: 人工神经网络(Artificial Neural Network)是一种新兴的具有自我学习能力的计算系统,在模式识别.函数逼近及贷款风险评估等诸多领域有广泛的应 ...

  8. Python之日志操作(logging)

    import logging   1.自定义日志级别,日志格式,输出位置 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s | ...

  9. js 禁止鼠标和键盘行为

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  10. Sencha touch中Ext.List的使用及高度自适应

    最近在做 Sencha 的一个项目,需要用到 Ext.List 来列出所需商品及相关信息,平时我们使用 Ext.List 都是使用  fullscreen:true  来设置 List 全屏显示, 但 ...