3668: [Noi2014]起床困难综合症

3668: [Noi2014]起床困难综合症

https://www.lydsy.com/JudgeOnline/problem.php?id=3668

分析:

  每一位分开考虑。

  算出每一位为1,计算完后是否产生贡献,每一位为0是否会产生贡献。

  然后从高位考虑:

  1. 如果这一位为0,并且可以产生(1<<i)的贡献,那么就让它为0。
  2. 如果这一位位1,可以产生贡献,并且在小于等于m,就让它为1。
  3. 不可以产生贡献的话,直接为0.

  如果在某一步,可以比m小了,就是m这位为1,而答案是0了,那么后面的就可以随便选了,否则,这位选的数必须小于等于m的这位。

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<cctype>
 7 #include<set>
 8 #include<vector>
 9 #include<queue>
10 #include<map>
11 #define fi(s) freopen(s,"r",stdin);
12 #define fo(s) freopen(s,"w",stdout);
13 using namespace std;
14 typedef long long LL;
15 
16 inline int read() {
17     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
18     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
19 }
20 
21 const int N = 100005;
22 
23 char s[N][5];
24 int a[N], f[N], n, m;
25 
26 int Calc(int x) {
27     for (int i=1; i<=n; ++i) 
28         if (s[i][0] == 'A') x &= a[i];
29         else if (s[i][0] == 'O') x |= a[i];
30         else if (s[i][0] == 'X') x ^= a[i];
31     return x;
32 }
33 
34 int main() {    
35     n = read(), m = read();
36     for (int i=1; i<=n; ++i) {
37         scanf("%s%d", s[i], &a[i]);
38     }
39     int t = Calc(0);
40     for (int i=30; i>=0; --i) f[i] = Calc(1 << i) & (1 << i);
41     int ans = 0;
42     bool flag = false;
43     for (int i=30; i>=0; --i) {
44         if ((t >> i) & 1) { 
45             ans += (1 << i);
46             if ((m >> i) & 1) flag = true;
47         }
48         else if (f[i]) {
49             if (flag) ans += f[i];
50             else if ((m >> i) & 1) ans += f[i]; 
51         }
52         else if ((m >> i) & 1) flag = true;
53     }
54     cout << ans;
55     return 0;
56 }
原文地址:https://www.cnblogs.com/mjtcn/p/9755029.html