• uva10718


    题目:uva10718 - Bit Mask(贪心)


    题目大意:给出32位无符号的整数n ,给定边界L和R,要求在这个边界里面找出一个整数,它和N做或运算得到的值最大。


    解题思路:要求做或运算得到的值最大,先N化成2进制的数,然后要使得结果最大的话,最好的就是【L,R】里面的某个数M能和N二进制数01互补.

    比如: 00000111

              那么M最好就是 11111000

              当然这个M须要满足【L,R】内。

              思路是M先先等于L,将L也转换成二进制数,然后和N的二进制,每一位都进行推断。

              假设N的某i位上面是0,而M上相应的位也是0,那么能够考虑将M上的这一位变成1,可是的推断是否M在【L,R】区间内,假设超过了,那么另一种可能就是为了保全这个位而将后面的位置为0,这种M与N的结果肯定必保留后面的位的结果要大。  

             假设N上的某i位是1,而M上相应的也是1,那么依据题意要最小的M,这里就能够考虑能否去掉这个1,相同也是要保证在LR之间,假设较小了,也还是有一种策略:为了使得M的值更小,而且i位的结果仍然不变,能够将这一位1去掉,而将后面的全部的位全置为1。这样尽管后面可能有不须要的1,可是这个能够后面处理。

              一个0一个1就是最好的状态了,不用处理。

             要用 long long 。


    代码:

    #include <stdio.h>
    #include <string.h>
    
    const int N = 32;
    typedef long long ll;
    ll t[N];
    bool w1[N], w2[N];
    //打表 二进制数每一位的单位
    void init () {
    	
    	t[0] = 1;
    	for (int i = 0; i < N - 1; i++)
    		t[i + 1] = t[i] * 2;	
    }
    //拆分成二进制数
    void cut (ll n, bool w[]) {
    
    	for (int i = N - 1; i >= 0; i--) {
    		if (n >= t[i]) {
    
    			w[i] = 1;
    			n -= t[i];
    		}
    	}
    }
    
    ll solve (ll l, ll r) {
    
    	ll ans = l;
    	for (int i = N - 1; i >= 0; i--) {
    
    		if (!w1[i] && !w2[i]) {  //都是 0
    
    			if (ans + t[i] <= r)
    				ans += t[i];
    			else {            
    				
    				ll temp = 0;
    				for (int j = i - 1; j >= 0; j--)   //计算后面的位是1的
    					if (w2[j])
    						temp += t[j];
    				if (ans + t[i] - temp >= l && ans + t[i] - temp <= r) {
    					
    					ans = ans + t[i] - temp;	
    					for (int j = i - 1; j >= 0; j--)
    						w2[j] = 0;
    				}
    			}
    		}
    
    		if (w1[i] && w2[i]) {  //都是1
    
    			if (ans - t[i] >= l)
    				ans -= t[i];
    			else {
    			
    				ll temp = 0;
    				for (int j = i - 1; j >= 0; j--)    //计算后面位是0的
    					if (!w2[j])
    						temp += t[j];
    				if (ans - t[i] + temp >= l && ans - t[i] + temp <= r) {
    
    					ans = ans - t[i] + temp;
    					for (int j = i - 1; j >= 0; j--)
    						w2[j] = 1;
    				}
    			}
    		}
    	}
    	return ans;
    }
    
    int main () {
    	
    	ll n, l, r;
    	init();
    	while (scanf ("%lld%lld%lld", &n, &l, &r) != EOF) {
    
    			memset(w1, 0, sizeof(w1));
    			memset(w2, 0, sizeof(w2));
    			cut(n, w1);
    			cut(l, w2);
    			printf ("%lld
    ", solve(l, r));
    	}
    	return 0;
    }


  • 相关阅读:
    40. Combination Sum II
    39. Combination Sum
    找一找
    37. Sudoku Solver
    Activiti 多个并发子流程的应用
    BPMN2新规范与Activiti5
    BPMN这点事-BPMN扩展元素
    JAVA规则引擎 -- Drools
    工作流Activiti5流程变量 任务变量 setVariables 跟 setVariablesLocal区别
    activiti 学习( 三 ) 之 流程启动者
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4505105.html
Copyright © 2020-2023  润新知