http://uoj.ac/problem/2 (題目鏈接)
題意:給出n個操作包括And,or,xor,求從0~m中的一個數使得經過這些操作後得到的值最大。
Solution
大水題。。貪心由高到低枚舉二進制上每一位:這一位爲0,經過操作後當前位變爲1,那麼就把這一位定爲0;這一位爲1,經過操作後仍然爲1,且當前答案加上這一位後不超過m,那麼就把這一位定爲1;無論是0還是1經過操作後都爲0,那麼當然是選0,保證答案儘可能小。
代碼:
// uoj2
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<queue>
#define MOD 1000000007
#define inf 2147483640
#define LL long long
#define free(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout);
using namespace std;
const int maxn=100010;
struct data {int t,op;}a[maxn];
int bin[31],n,m,x;
char s[10];
int cal(int x,int val) {
for (int i=1;i<=n;i++) {
if (a[i].op==0) val&=a[i].t;
else if (a[i].op==1) val|=a[i].t;
else val^=a[i].t;
}
if (val&x) return 1;
else return 0;
}
int main() {
bin[0]=1;for (int i=1;i<=30;i++) bin[i]=bin[i-1]<<1;
scanf("%d%d",&n,&m);
char s[10];
for (int i=1;i<=n;i++) {
scanf("%s%d",s,&a[i].t);
if (s[0]=='A') a[i].op=0;
else if (s[0]=='O') a[i].op=1;
else a[i].op=2;
}
int l=30,ans=0;
if (m!=0) {
for (;bin[l]>m;l--);
for (int i=l;i>=0;i--) {
if (cal(bin[i],0)) continue;
else if (cal(bin[i],bin[i]) && ans+bin[i]<=m) ans+=bin[i];
}
}
for (int i=1;i<=n;i++) {
if (a[i].op==0) ans&=a[i].t;
else if (a[i].op==1) ans|=a[i].t;
else ans^=a[i].t;
}
printf("%d",ans);
return 0;
}