您的位置:首页 > 其它

"尚学堂杯"哈尔滨理工大学第七届程序设计竞赛 G.Great Atm(二进制,位运算)

2017-04-04 20:49 316 查看
题目:

fdc0
G.Great Atm
Time Limit: 1000 MSMemory Limit: 32768 K
Total Submit: 615
(191 users)
Total Accepted: 40
(36 users)
Special Judge: No
Description
An old story said the evil dragon wasn’t evil at all, only bewitched, and now that the riddles were solved it was proving to be as kind as its new master.

A powerful warrior Atm is going to solve the riddles. First, he should beat the evil wizard. The road from Atm’s castle to wizard’s lab is filled with magic traps. The magic trap will affect Atm’s combat effectiveness.

Atm’s combat effectiveness can be considered as an integer. Effect of magic trap can be considered as mathematical operation. The three kinds of magic traps correspond to three kind of bit operation. (AND, OR and XOR)

Atm can adjust his equipment to change his initial combat effectiveness from 0 to m (include 0 and m). He wants when he arrives the wizard’s lab, his combat effectiveness can be maximum.
Input
There are multiple test cases.

For each test cases:

The first line contains two integers n(1<=n<=10^5) and m(1<=m<=10^9), indicating the number of magic traps and the maximum of initial combat effectiveness.

Each of the next n lines contains a string and an integer, indicating the bit operation. The string will be “AND”, “OR” or “XOR” correspond to AND operation (&), OR operation (|) or XOR operation (^). The integer t(1<=t<=10^9) is second operand in the operation.

Output
For each test cases, a line contains an integer, indicating the maximum combat effectiveness when he arrives the wizard's lab.
Sample Input
3 10

AND 5

OR 6

XOR 7
Sample Output
1
SubmitMessage
思路:
这个题困扰了我两天,今天终于想通了。

先说题意:给你了两个数n和m,n代表接下来几组数据,m代表了一个从0--m的范围,问你在0--m里面,用这里面的数进行下面的几组位运算,可以得到的最大值是多少。

首先,暴力肯定超时。所以我们要从二进制的方式来进行考虑,一个Int型的数有32位,除去符号位还有31为,这31位得数中最大的是二进制位全部为1,转化成16进制也就是0x7fffffff,而最小的数的二进制位全部为0,那么肯定就是0了。

然后用这个二进制的最大值和二进制的最小值,进行下面几组给出的运算。

利用移位运算计算出这两个值的每一位与1进行与运算所得到的结果。

最后遍历二进制的31位,如果原先这一位为0,但操作后的结果中这一位为1,那么最后的答案肯定要加上这一位(≤m的数中这一位肯定可以为0); 
如果原先这一位为1,操作后的结果中这一位也为1,此时我们要先判断这一位的十进制是否大于m,如果不大于那么最后答案也要加上这一位(因为≤m的数中这一位可以为1),最后加得的答案就是最终的结果了

代码:

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <stack>
#include <queue>
#include <vector>
#include <algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define N 1000+20
#define inf 0x3f3f3f3f
#define M 1000000+2000
#define LL long long
using namespace std;
int temp[40][2];
int main()
{
int n,m,x;
char s[10];
while(~scanf("%d%d",&n,&m))
{
int maxx=0x7fffffff,minn=0;//maxx代表除了符号位其他的为为1的最大值,minn的二进制都是0
for(int i=0; i<n; ++i)
{
scanf("%s %d",s,&x);
if(s[0]=='A')//AND
maxx&=x,minn&=x;
else if(s[0]=='O')//OR
maxx|=x,minn|=x;
else if(s[0]=='X')//XOR
maxx^=x,minn^=x;
}
//31位数的范围是0--30
for(int i=30; i>=0; i--)//记录二进制的每一位为0或为1时所得的(二进制中这一位的)结果
{
temp[i][0]=(minn&(1<<i));//这一位为0还是1
temp[i][1]=(maxx&(1<<i));
}
int ans=0;
for(int i=30; i>=0; i--)
{
if(temp[i][0])
ans=ans|(1<<i);
else if(temp[i][1])
{
if((1<<i)<=m)
{
ans=ans|(1<<i);
m-=(1<<i);
}
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐