题意:

  给出一个范围[m,n],按照二进制表示中的1的个数从小到大排序,若1的个数相同,则按照十进制大小排序。求排序后的第k个数。注意:m*n>=0。

思路:

  也是看论文的。一开始也能想到是这种解法,枚举0~31个1,逐步缩小第k个数的范围(其实就是找到第k个数应该有几个1),然后二分答案,直到找到第k个数。

  我只是在找第k个数时不是二分答案,而是想直接从最高位往低位走,判断左子树中满足条件的数的数量,然后控制往下一位应该是0还是1(即往树的哪一个孩子方向走,直到根)。其实也是二分思想。

  这题明显只有两个范围:[-INF,0]或者[0,INF],要特别注意n=0或者m=0的情况,有可能第k个数就是0,否则,是不是0就没有什么影响了。

  1 //#include <bits/stdc++.h>
  2 #include <iostream>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <map>
  7 #include <algorithm>
  8 #include <vector>
  9 #include <iostream>
 10 #define pii pair<int,int>
 11 #define INF 0x7f3f3f3f
 12 #define LL long long
 13 using namespace std;
 14 const double PI  = acos(-1.0);
 15 const int N=35; //注意大小
 16
 17 int f[N][N], bit[N], m, n, k;;
 18 void pre_cal()  //预处理组合数
 19 {
 20     f[0][0]=1;
 21     for(int i=1; i<N; i++) //位数
 22     {
 23         f[i][0]=f[i][i]=1;
 24         for(int j=1; j<i; j++) //多少个1
 25         {
 26             f[i][j]=f[i-1][j]+f[i-1][j-1];
 27         }
 28     }
 29 }
 30
 31 int cal(int n,int k,int b)
 32 {
 33     memset(bit, 0, sizeof(bit));
 34     int len=0, cnt=0, ans=0;
 35     while(n)    //转成b进制
 36     {
 37         bit[++len]=n%b;
 38         n/=b;
 39     }
 40     for(int i=len; i>0; i--)
 41     {
 42         if( bit[i]==1 )
 43         {
 44             ans+=f[i-1][k-cnt]; //统计左边的
 45             if(++cnt>k)   break;  //已超
 46         }
 47     }
 48     if(cnt==k)  ans++;
 49     return ans;
 50 }
 51
 52
 53 int get_ans(int m,int n,int k)
 54 {
 55     int i, num;
 56     for(i=0; i<=31; i++)    //枚举位数
 57     {
 58         num=cal(n,i,2)-cal(m-1,i,2);
 59         if(k-num<=0)    break;
 60         else   k-=num;
 61     }
 62     int L=m,R=n;
 63     while( L<R )            //二分答案
 64     {
 65         int mid=R-(R-L+1)/2;
 66         num=cal(mid,i,2)-cal(m-1,i,2);
 67         if( num<k ) L=mid+1;
 68         else        R=mid;  //如果等于,也是继续缩小范围的
 69     }
 70     return R;
 71 }
 72
 73
 74 int main()
 75 {
 76     //freopen("input.txt","r",stdin);
 77     pre_cal();
 78     int t;cin>>t;
 79     while(t--)
 80     {
 81         scanf("%d%d%d",&m,&n,&k);
 82         if(m<0)
 83         {
 84             m^=(1<<31); //改为正
 85             if(n==0)    //上界为0
 86             {
 87                 n--;
 88                 n^=(1<<31);
 89                 if(get_ans(m,n,k-1)==n) printf("0\n");
 90                 else cout<<(get_ans(m,n,k)^(1<<31))<<endl;
 91             }
 92             else
 93             {
 94                 n^=(1<<31);
 95                 cout<<(get_ans(m,n,k)^(1<<31))<<endl;  //恢复负值
 96             }
 97         }
 98         else
 99         {
100             if(m==0&&k==1)   {printf("0\n");continue;}
101             else if(m==0)    m++,k--;
102             cout<<get_ans(m,n,k)<<endl;
103         }
104     }
105     return 0;
106 }

AC代码

转载于:https://www.cnblogs.com/xcw0754/p/4852036.html

SPOJ SORTBIT Sorted bit squence (数位DP,入门)相关推荐

  1. hdu 2089 数位dp入门

    HDU 2089 题意:中文题 思路:数位dp入门题 AC代码: #include "iostream" #include "string.h" #includ ...

  2. 数位dp入门题 洛谷P2657 [SCOI2009] windy 数

    题干 传送门 windy 定义了一种 windy 数. 题目描述 不含前导零且相邻两个数字之差至少为 2的正整数被称为 windy 数.windy 想知道,在 a 和 b 之间,包括 a 和 b ,总 ...

  3. 数位DP入门+数位DP模板

    数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满足一些条件数的个数.所谓数位dp,字面意思就是在数位上进行dp咯.数位还算是比较好听的名字,数位的含义:一个数有个位.十位.百位.千 ...

  4. 数位 DP 入门 (不要 62+windy 数)

    \[I\] 平常的做法是设 \(f_{i,j}\) 为 \(0\)~\(j \times 10^{i-1}\) 的合法个数,这里用某种神奇而快速的做法. 简化题意: 不要 \(6\ 2\) 连在一起的 ...

  5. 数位DP 学习笔记1(数位DP入门)

    HDU 2089 不要62: 题目大意是给你一个区间,让你统计这个区间里不包含 4 和 62 的数字的个数. 最朴素的思路是: 对于每个区间 [l, r],遍历所有在区间 [l, r] 里的数字,然后 ...

  6. P2657 [SCOI2009]windy数 数位dp入门

    参考了题解,理解仍然还不够透彻 #include<bits/stdc++.h> using namespace std; const int N=550; const int maxn=1 ...

  7. 牛客网 G-送分了 QAQ 数位 dp入门

    时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 题目描述 链接: https://www.nowcode ...

  8. 数位DP入门笔记(1)HUD-2089

    题目: 题目理解和思路: 1.此题是给一个6位车牌号,正着不能含有连着的62,不能有4. 2.判断车牌号可能会采用dfs,因为每增加一位数就包含带4,或者形成62两种不合法情况(可以用但此代码没有用到 ...

  9. 数位DP入门之hdu 3652 B-number

    hdu 3652 B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer ...

最新文章

  1. VueJs路由跳转——vue-router的使用
  2. 前端遍历导致查询数据时间过长_OLAP 服务器,空间换时间可行吗?
  3. 多值参数-定义及作用
  4. 运行第一个docker容器
  5. 上海应用技术学院c语言实验报告9,上海工程技术大学C语言实验报告
  6. 嘌呤含量高的食物大全
  7. linux 脚本使用第一篇
  8. 为全力发展AIOT,小米把松果电子分拆重组了
  9. 面试官问:Mybatis Plus 是如何实现动态 SQL 语句的?原理你懂吗?
  10. 利用【监听器】动态加载Log4j配置文件
  11. C++解析char *p与char p[]
  12. 简易语音助手—python
  13. 手把手教你用python写游戏
  14. 基于Matlab的人脸识别设计(PCA)
  15. python如何使用jieba库_Python jieba库的使用
  16. 使用讯飞tts实现安卓语音中文合成播报
  17. 双11为什么成了传统电商的流量批发市场?
  18. 部署大宗商品撮合交易平台,实现高效交易与资源信息对接
  19. UG NX1980一键安装正式版+安装说明(安装简单)
  20. Protect访问权限

热门文章

  1. note同步不及时 one_一辆理想ONE又“跪了”?理想官方紧急发文回应
  2. linux 账号密码 字段,详解Linux中的用户密码管理命令passwd和change
  3. 克隆安装oracle,Oracle 之 Cloning $oracle_home (克隆安装oracle软件)
  4. android版本如何修改时间,如何修改Android系统默认时间
  5. 卷积神经网络语音识别_用于物体识别的3D卷积神经网络
  6. java 继承示例_Java中的继承类型以及示例
  7. python如何操作oracle数据库_python操作oracle数据库
  8. 手动打开和关闭windows的相关服务
  9. UVA 11988——Broken Keyboard (a.k.a. Beiju Text)
  10. uva 10120——Gift?!