UVA 10714 Bit Mask

题目要求:,给出三个32位数字,N,L,U(L<=U),找到一个数字M(L<=M<=U),使得N|M的结果最大,并且M最小

贪心的方式来处理,首先设法找到最大值,把每个数字转换成数组来进行处理,对于N,高位到低位,如果数组位数为0,那么尝试将M的对应位数设置为1,如果设置为1之后。

不大于上界U,那么这个方式合理,继续查找。另外需要注意的是如果N对应位数为0将M对应位置设置为1后,需要将设置为1的后面的所有都置0判断是否大于上界。

这句话可能不太好理解,参考数据 5,7,8.答案输出应该是8,在转换过程中存在0111,进行转换,如果直接转换成1111,那么肯定大于U,需要转换为1000进行一下判断,

所有才有代码中的temp和intcpy。

另外捉急位运算只知道规则。还是不太会用。这里全部用数组来模拟,捉急。。需要学习一下大牛的代码,虽然AC了。。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include<cctype>
#include <ctime>
#include <deque>
#include <stack>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define LL long long
#define PI 3.1415926535897932626
using namespace std;
int gcd(int a, int b)
{
	return a % b == 0 ? b : gcd(b, a % b);
}
//  
int change[32];
int ans;
long N,L,U;
int len;
int res[32];
int temp[32];
int bit;//转换N之后的数字位数
inline long long power(int n)
{
    long long ans=1;
    for (int i=1;i<=n;i++)
        ans*=2;
        return ans;
}
inline void tran_arr()//将数字N转换进入数字
{
     bit=0;int tmp[32];len=0;
     memset(tmp,0,sizeof(tmp));
    while (N>1)
    {
        tmp[bit++]=N%2;
        N/=2;
    }
    tmp[bit++]=N%2;//这里要更改以32位为基础,将这些数字平移到尾侧
    for (int i=bit-1,j=32-bit;i>=0;i--,j++)
        change[j]=tmp[i];
    /*for (int i=0;i<32;i++) printf("%d",change[i]);
    putchar('\n');*/
    while (L>1)
    {
        tmp[len++]=L%2;
        L/=2;
    }
    tmp[len++]=L%2;
    for (int i=len-1,j=32-len;i>=0;i--,j++)
        res[j]=tmp[i];
    /*for (int i=0;i<32;i++) printf("%d",res[i]);
    putchar('\n');*/
}
inline long long tran_int()
{
    long long  sum=0;
    for (int i=0;i<32;i++)
       if (res[i])
        sum+=power(31-i);
        //printf("%lld\n",sum);
        return sum;
}
inline void intcpy(int *temp,int *res)
{
    for (int i=0;i<32;i++)
        temp[i]=res[i];
}
void slove()
{
    tran_arr();//刚开始的res就是最小值注意,下面的程序中只能使他变大
    int cas=0;
    for (int i=0;i<32;i++)
    {
        if (change[i]==0)
        {
             if (res[cas]==0)
             {
                 intcpy(temp,res);
                 res[cas]=1;//复制到temp
                 for (int k=i+1;k<32;k++)res[k]=0;
                 if (tran_int()>U)intcpy(res,temp);//如果不超过届那么不用更改
             }
        }
        cas++;
    }
    printf("%lld\n",tran_int());
}
int main()
{
    while (scanf("%lld%lld%lld",&N,&L,&U)==3)
    {
        //M的下界是L,上届是U
        memset(res,0,sizeof(res));
        memset(change,0,sizeof(change));
        slove();
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值