您的位置:首页 > 产品设计 > UI/UE

spoj1182 Sorted bit squence

2015-08-13 22:22 477 查看
题目大意:给你一个区间[m,n],把这个区间里的数字排序,排序的规则是按照二进制1的个数从少到多排,如果个数相同,则按照大小排序。让你求第k小的数是谁

此题可利用ural1057的方法,先计算出从m到n这个区间中含有1个1的有几个,含有2个1的有几个一直到含有31个1的有几个,然后与k进行比较,看第k小的数字应该是含有几个1的,假设含有pos个1,然后从区间左端点开始二分答案,如果从区间左端点到mid含有pos个1的数小于等于k个,就让l = k + 1,否则r = k;然后再求出新的mid进行比较

AC代码

<span style="font-family:KaiTi_GB2312;font-size:18px;">#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int f[35][35];
void init()
{
memset(f,0,sizeof(f));
f[0][0] = 1;
for(int i = 1; i <= 32; i++)
{
f[i][0] = f[i-1][0];
for(int j = 1; j <= i; j++)
f[i][j] = f[i-1][j] + f[i-1][j-1];
}
}
int slove(int x, int k)
{
int tot = 0,ans = 0;
for(int i = 31; i > 0; i--)
{
if(x & (1 << i))
{
tot ++;
if(tot > k) break;
x = x^(1 << i);
}
if((1 << (i - 1)) <= x)
ans += f[i-1][k - tot];
}
if(tot + x == k) ans ++;
return ans;
}
int cal(int m,int n, int k)
{
int pos = 1;
for(int i = 1; i <= 31; i++)
{
int cnt = slove(n,i) - slove(m-1,i);
//printf("cnt%d ",cnt);
if(k <= cnt) //相等的时候也是含有i个1
{
pos = i;
break;
}
k-=cnt;
}
//printf("pos%d %d\n",pos,k);
int l = m, r = n,mid;
while(l < r)
{
mid =(int)(((long long)l + (long long)r)/2); //进行强制类型转换,两个int相加可能会超int
//printf("%d %d %d\n",l,r,mid);
int tem = slove(mid,pos) - slove(m - 1,pos);
if(tem < k)
l = mid+1;
else
r = mid;
}
return l;
}
int main()
{
init();
int t,m,n,k;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&m,&n,&k);
if(m == 0 && n == 0)
{
printf("0\n");
continue;
}
if( m >= 0 && n >= 0)
{
if(m == 0)
{
k--;
m = 1;
}
if(k == 0)
{
printf("0\n");
continue;
}
//printf("%d %d %d\n",m,n,k);
printf("%d\n",cal(m,n,k));
}
else
{
if(n == 0)
{
k--;
n = -1;
if(k == 0)
{
printf("0\n");
continue;
}
}
m &= (~(1<<31));
n &= (~(1 << 31));
printf("%d\n",(1 << 31)|cal(m,n,k));
}
}
}
</span>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数位统计