[洛谷 P2114] [NOI2014]起床困难综合症

原题传送门

此题的思想还是位运算&状压DP

位运算的特点是二进制下不进位,故参与位运算的各位之间是相互独立的

X0的第k位应该填为1仅当在下面两种情况时出现:

  1. 已有数值+1<
  2. 用每个参数的第k位参与运算,若初值为1,那么经过n次操作后结果为1,0时同理

这样,我们就可以用类似于贪心的思想,得到尽可能大的结果

直接大力设结果,爆算每一位。。

Code:

#include 
#define int long long
using namespace std;
const int maxn = 100010;
int n, m, x;
pair a[maxn];
inline int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch))
        f = (ch == '-') ? -1 : 1, ch = getchar();
    while (isdigit(ch))
        x = x * 10 + (ch - '0'), ch = getchar();
    return x * f;
}
inline int cal(int bit, int now)
{
    for (int i = 1; i <= n; i++)
    {
        int x = a[i].second >> bit & 1;
        if (a[i].first == "AND")
            now &= x;
        else if (a[i].first == "OR")
            now |= x;
        else
            now ^= x;
    }
    return now;
}
signed main()
{
    n = read(), m = read();
    for (int i = 1; i <= n; i++)
    {
        char str[5];
        int x;
        scanf("%s%d", str, &x);
        a[i] = make_pair(str, x);
    }
    int val = 0, ans = 0;
    for (int bit = 29; bit >= 0; bit--)
    {
        int res0 = cal(bit, 0);
        int res1 = cal(bit, 1);
        if (val + (1 << bit) <= m && res0 < res1)
            val += 1 << bit, ans += res1 << bit;
        else
            ans += res0 << bit;
    }
    cout << ans << '\n';
}

你可能感兴趣的:([洛谷 P2114] [NOI2014]起床困难综合症)