思路:因为一个二进制数做位运算,每个位的位运算独立,所以并不要枚举每个数,枚举每个二进制位分别是0或1,看运算完后的结果。 AC代码:

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
int a[35];
int b[35];
int main()
{
    ios::sync_with_stdio(0);cin.tie(0);
    memset(a, 0 , sizeof(a));
    for(int i=0; i<=34; ++i)
    {
        b[i]=1;
    }
    int n,m,t;cin>>n>>m;
    string tstr;
    for(int i=1; i<=n; ++i)
    {
        cin>>tstr>>t;
        if(tstr == "OR")
        {
            for(int j=2 ; j<= 32; ++j)
            {
                a[j] |= ( (t>>(32-j)) & 1 );//别写成1>>(32-j)了
                b[j] |= ( (t>>(32-j)) & 1 );//别写成1>>(32-j)了
            }
        }
        else if(tstr == "XOR")
        {
            for(int j=2 ; j<= 32; ++j)
            {
                a[j] ^= ( (t>>(32-j)) & 1 );//别写成1>>(32-j)了
                b[j] ^= ( (t>>(32-j)) & 1 );//别写成1>>(32-j)了
            }
        }
        else 
        {
            for(int j=2 ; j<= 32; ++j)
            {
                a[j] &= ( (t>>(32-j)) & 1 );//别写成1>>(32-j)了
                b[j] &= ( (t>>(32-j)) & 1 );//别写成1>>(32-j)了
            }
        }
    }
    int res=0;
    int power=0;//因为上面说了两个位操作的数都非负,那么最高位恒为0,0作上述的位运算,怎么做也不可能变成1.但如果加入了同或,那么这里就要改为long long,然后单独判断第一位是否能为1
    for(int k=32; k>=2; --k)
    {
        if(a[k] == 1) {power |= 1<<(32-k);continue;}//原来是0,使得不超过m的可能性大,操作完是1,使得power尽可能大,两全其美
        if(b[k] == 1 && ( (res | (1<<(32-k)) ) <= m ) ) {power |= 1<<(32-k);res |= 1<<(32-k);}//原来是1改完是0还不如原来是0改完是0,如果原来是1改完是0,且改完后不超过可以改。
    }
    cout<<power;
    return 0;
}

PS:如果从高位开始遍历,其实没区别 只要把for循环改为for(int k=2; k<=32; ++k)就好