数位dp--spoj1182

来源:互联网 发布:小受坐轮椅卖淘宝 编辑:程序博客网 时间:2024/05/21 22:30

1182. Sorted bit squence

Problem code: SORTBIT

Let's consider the 32 bit representation of all integers i from m up to n inclusive (m ≤ i ≤ n; m × n ≥ 0, -2^31 ≤ m ≤ n ≤ 2^31-1). Note that a negative number is represented in 32 bit Additional Code. That is the 32 bit sequence, the binary sum of which and the 32 bit representation of the corresponding positive number is 2^32 (1 0000 0000 0000 0000 0000 0000 0000 0000 in binary).

For example, the 32 bit representation of 6 is 0000 0000 0000 0000 0000 0000 0000 0110

and the 32 bit representation of -6 is 1111 1111 1111 1111 1111 1111 1111 1010

because

0000 0000 0000 0000 0000 0000 0000 0110 (6) 

1111 1111 1111 1111 1111 1111 1111 1010 (-6) 
-------------------------------------------------
= 1 0000 0000 0000 0000 0000 0000 0000 0000 (2^32)

Let's sort the 32 bit representations of these numbers in increasing order of the number of bit 1. If two 32 bit representations that have the same number of bit 1, they are sorted in lexicographical order.

For example, with m = 0 and n = 5, the result of the sorting will be

No.

Decimal number

Binary 32 bit representation

1

0

0000 0000 0000 0000 0000 0000 0000 0000

2

1

0000 0000 0000 0000 0000 0000 0000 0001

3

2

0000 0000 0000 0000 0000 0000 0000 0010

4

4

0000 0000 0000 0000 0000 0000 0000 0100

5

3

0000 0000 0000 0000 0000 0000 0000 0011

6

5

0000 0000 0000 0000 0000 0000 0000 0101

with m = -5 and n = -2, the result of the sorting will be

No.

Decimal number

Binary 32 bit representation

1

-4

1111 1111 1111 1111 1111 1111 1111 1100

2

-5

1111 1111 1111 1111 1111 1111 1111 1011

3

-3

1111 1111 1111 1111 1111 1111 1111 1101

4

-2

1111 1111 1111 1111 1111 1111 1111 1110

Given m, n and k (1 ≤ k ≤ min{n − m + 1, 2 147 473 547}), your task is to write a program to find a number corresponding to k-th representation in the sorted sequence.

Input

The input consists of several data sets. The first line of the input file contains the number of data sets which is a positive integer and is not bigger than 1000. The following lines describe the data sets.

For each data set, the only line contains 3 integers m, n and k separated by space.

Output

For each data set, write in one line the k-th number of the sorted numbers.

Example

Sample input:20 5 3-5 -2 2Sample output:2-5 

#include<cstdio>int dp[40][40];int getv(int n,int k){  //统计[0,n]二进制有k个1的数字个数    int res=0,tot=0;    for(int i=31;i>0;i--){        if(n&1<<i){            tot+=1;            if(tot>k) break;            n^=1<<i;        }        if(n&1<<i-1){            res+=dp[i-1][k-tot];        }    }    if(tot+n==k) res++;    return res;}int main(){    dp[0][0]=1;    for(int i=1;i<=32;i++){        dp[i][0]=dp[i-1][0];        for(int j=1;j<=i;j++)            dp[i][j]=dp[i-1][j]+dp[i-1][j-1];    }    int t,a,b,c,zf;    bool flag;    scanf("%d",&t);    while(t--){        flag=true;        scanf("%d%d%d",&a,&b,&c);        /************边界处理**************/        if(a==0&&b==0){puts("0");continue;}        if(a==0){            if(c==1) {puts("0");continue;}            a=1;c-=1;        }        if(b==0){            if(c==1) {puts("0");continue;}            b=-1;c-=1;        }        if(b<0) {b&=-1u>>1;a&=-1u>>1;flag=false;}        if(a==0){            if(c==1) {printf("%d\n",1<<31);continue;}            a=1;c-=1;        }        int tot=0,ans;        for(int i=1;i<=31;i++){           ans=getv(b,i)-getv(a-1,i);           tot+=ans;           if(tot>=c) {zf=i;break;}        }        ans-=tot-c; //1的位数为zf,从小到大排第ans个        while(a<b){ //二分求解            int mid=(b-a>>1)+a; //防溢出            int tmp=getv(mid,zf)-getv(a-1,zf);            if(tmp<ans) {a=mid+1;ans-=tmp;}            else b=mid;        }        if(flag) printf("%d\n",a);        else printf("%d\n",a|1<<31);    }    return 0;}


题意:给定一个区间,求这个区间按照该排序规则排序后的第k个数,排序规则:数对应的二进制中1的个数少的排在多的前面,1的个数相同则按照数字大小顺序排列。

一道比较水的数位dp,首先要确定这第k个数处在哪一个数段中,即1的个数为多少,其次要确定这个数在这个数段中是第几个。前面一个过程就是数位dp做的,后一个过程就是个二分。

这题负数比较麻烦,但是发现可以将其最高位符号位改成0,转换成正数做,结果是一样的。还有0是比较麻烦的,这个需要做仔细的边界处理,还负数的最小值,转换成正数,其实变成了0,也许特殊处理。然后就可以统一处理了,得到结果,如果原先是负数,不要忘了在最高位添上1。


0 0
原创粉丝点击