uva--10718+贪心

题意:

    输入n,L,U,在L,U之间找一个数M使得n与M按位或的值最大,如果有多个M输出最小的那个。

思路:

   将数化成二进制再结合或的性质就可以很容易得到一个贪心的策略:将n化为32位的二进制表示后

对于n中为0的位,使得M对应的二进制位为1.这样显然可以使得n|M值最大,但是同时还要考虑区间的限制;

n中二进制为0时,M对应的二进制位取1的条件是:必须保证后面M的最小值小于U,否则取0;n中二进制为1时,如果

M中对应位取0,则必须保证对应的M最大值要大于L,否则就要取1;


代码:


#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
using namespace std;

#define LL long long

int main()
{
      LL n,L,R,a[100];
      int i,j;
      while(scanf("%lld%lld%lld",&n,&L,&R)!=EOF)
      {
               LL sum=0,min1,max1;
               int k=0;
               memset(a,0,sizeof(a));
               while(n)
               {
                     a[k++]=n%2;
                     n=n/2;
               }
               k=32;
               for(i=k-1;i>=0;i--)
               {
                   if(!a[i]&&sum+pow(2,i)<=R)
                          sum+=pow(2,i);
                   else
                   {
                           max1=sum+pow(2,i)-1;
                          if(max1<L)
                                sum+=pow(2,i);
                   }
               }
               printf("%lld\n",sum);
      }
 return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值