HDU 5491 The Next 构造(2015 ACM/ICPC Asia Regional Hefei Online)

【链接】click here~~

【题意】:

给你一个D(0≤D<231),保证D的二进制中1的数量在s1和s2之间

然后让你求一个最小的数,使得这个数的二进制数量大于等于s1,小于等于s2,且大于 d

【思路】虽然是比赛时候的一道水题,但是开始看到的时候并没有想到好的思路,最后还是学弟强行过掉,今天突然想到了可以用lowbit来求

首先看到D的范围是很大的,那么如何 构造呢?

这里举个例子:比如11,二进制表示(1011),取11+1=12,二进制表示(1100)s1=2,那么我们要做的就是考虑构造数的范围,如果当前数的s1 小于左区间的值,我们要做的就是从最后一个0出现的位置添加1,也就是从右到左,我们发现对12取按位反后得到(0011),取一次lowbit得到从右往左第一个1的位置是1,那么我们就把12+1=13(1101),相当于12的十进制加一,也等于12的二进制多添了一个1,这样是构造小于左区间的,那么如果大于左区间,又要满足条件,即取大于D的最小值,不难发现,只要加上lowbit(d)即可

代码:

/*
* Problem: HDU No.5491
* Running time: 499MS
* Complier: G++
* Author: javaherongwei
* Create Time:  8:47 2015/9/28 星期一
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
inline LL read(){
    int  c=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    return c*f;
}
LL bitwei(LL x){
    LL s=0;
    while(x){
        if(x%2) s++;
        x/=2;
    }
    return s;
}
LL bitwei2(LL x){
    x = (x&0x55555555) + ((x>>1) & 0x55555555);
    x = (x&0x33333333) + ((x>>2) & 0x33333333);
    x = (x&0x0F0F0F0F) + ((x>>4) & 0x0F0F0F0F);
    x = (x&0x00FF00FF) + ((x>>8) & 0x00FF00FF);
    x = (x&0x0000FFFF) + ((x>>16) & 0x0000FFFF);
    return x;
}

LL lowbit(LL x){
    return x&(-x);
}
int main()
{
    int t,tot=1;t=read();
    while(t--){
        LL d,s1,s2;
        d=read();s1=read();s2=read();d++;
        LL len=bitwei2(d);
        while(!(len>=s1&&len<=s2)){
            if(len<s1) d+=lowbit(~d);
            else d+=lowbit(d);
            len=bitwei2(d);
        }
        printf("Case #%d: ",tot++);
        printf("%lld\n",d);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-07-31 22:08:07

HDU 5491 The Next 构造(2015 ACM/ICPC Asia Regional Hefei Online)的相关文章

【动态规划】HDU 5492 Find a path (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5492 题目大意: 一个N*M的矩阵,一个人从(1,1)走到(N,M),每次只能向下或向右走.求(N+M-1)ΣN+M-1(Ai-Aavg)2最小.Aavg为平均值. (N,M<=30,矩阵里的元素0<=C<=30) 题目思路: [动态规划] 首先化简式子,得原式=(N+M-1)ΣN+M-1(Ai2)-(ΣN+M-1Ai)2 f[i][j][k]表示走到A[i][j]格子上,此时前i+j-1

【贪心】【模拟】HDU 5491 The Next (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5491 题目大意: 一个数D(0<=D<231),求比D大的第一个满足:二进制下1个个数在[s1,s2]范围内.D已经满足[s1,s2]. 题目思路: [贪心][模拟] 首先将这个数转成二进制统计总共1的个数s,再求出末尾连续0和1的个数n0,n1. 如果最后一位是0: s=s2,那么为了保证s<s2且答案>D,先设ans=d+lowbit(d),此时满足了新的s<s2且答案&g

HDU - 5491 The Next 2015 ACM/ICPC Asia Regional Hefei Online

从D+1开始,对于一个数x从它出发到x+lowbit(x)之前1的数量都是单调不减的,因此1的数量在一个范围内是一个区间. 每次判断一下有没有和[s1,s2]有没有交集. #include<bits/stdc++.h> using namespace std; inline int read() { char c; while(c=getchar(),c<'0'||c>'9'); int re = c-'0'; while(c=getchar(),c>='0'&&am

【二分】【最长上升子序列】HDU 5489 Removed Interval (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5489 题目大意: 一个N(N<=100000)个数的序列,要从中去掉相邻的L个数(去掉整个区间),使得剩余的数最长上升子序列(LIS)最长. 题目思路: [二分][最长上升子序列] 首先,假设去掉[i,i+m-1]这L个数,剩余的LIS长度为max(i左端最后一个不大于a[i+m]的LIS长度+a[i+m]开始到最后的LIS长度). 所以,我们从n到1逆向先求最长下降子序列的长度f[i],就可以知

【线段树】HDU 5493 Queue (2015 ACM/ICPC Asia Regional Hefei Online)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5493 题目大意: N个人,每个人有一个唯一的高度h,还有一个排名r,表示它前面或后面比它高的人的个数,求按身高字典序最小同时满足排名的身高排列. 题目思路: [线段树] 首先可以知道,一个人前面或后面有r个人比他高,那么他是第r+1高或第n-i-r+1高,i为这个人是第几高的. 所以先将人按照身高从小到大排序,接下来,把当前这个人放在第k=min(r+1,n-i-r+1)高的位置. 用线段树维护包

HDU 5444 Elven Postman (2015 ACM/ICPC Asia Regional Changchun Online)

[题目链接]:click here~~ [题目大意]: HDU 5444 题意:在最初为空的二叉树中不断的插入n个数.对于每个数,从根节点开始判断,如果当前节点为空,就插入当前节点,如果当前节点不为空,则小于当前节点的值,插入右子树,否则插入左子树. 接着q次询问,每次询问一个值在二叉树中从根节点开始的查找路径. 3 直接用二叉树模拟整个插入和询问的过程 代码: /* * Problem: HDU No.5444 * Running time: 0MS * Complier: G++ * Aut

Hdu 5459 Jesus Is Here (2015 ACM/ICPC Asia Regional Shenyang Online) 递推

题目链接: Hdu 5459 Jesus Is Here 题目描述: s1 = 'c', s2 = 'ff', s3 = s1 + s2; 问sn里面所有的字符c的距离是多少? 解题思路: 直觉告诉我们,sn肯定由sn-1与sn-2推导出来的.然后呢,我们可以看出 n%2==1 的时候 sn-1 与 sn-2 由 ffff 衔接起来的,n%2==0 的时候,sn-1 与 sn-2由 ff 衔接起来的.告诉队友后,队友就把这个当成重要依据推啊,推啊!!到最后感觉丢队友自己看药丸,放弃02回来和队友

HDU 5489 Removed Interval 2015 ACM/ICPC Asia Regional Hefei Online

定义f[i]表示以i为开头往后的最长上升子序列,d[i]表示以i为结尾的最长上升子序列. 先nlogn算出f[i], 从i-L开始枚举f[i],表示假设i在LIS中得到的最长上升子序列,往[0,i-L)里找到满足ai>aj中dj值最大的.用dj+f[i]更新. 但是这样会少考虑一种情况,即i-L以后都不在最终的答案里面,这样一定是以[0~i-L)中的某个结尾的,所以还要用d[j]去更新答案. #include<bits/stdc++.h> using namespace std; con

2015 ACM/ICPC Asia Regional Hefei Online

1001 Monitor the Alpacas 1002 The Relationship in Club 1003 Difference of Clustering 1004 Difference of Languages 1005 Shape 1006 Removed Interval 1007 Simple Matrix 1008 The Next 1009 Find a path 1010 Queue