判断掩码非法
m + (m & (-m)) || !(m + 1)

  • exp: 合法mask: 255.255.128.0
    m = 11111111 11111111 10000000 00000000
    (-m) = 00000000 00000000 10000000 00000000 (补码取反加一就是取负)
    m & (-m) = 00000000 00000000 10000000 00000000 (找到最后一个1)
    m + (m & (-m)) = 00000000 00000000 00000000 00000000 (如果mask合法,加最后一个1就会依次进位变为0,所以只要相加结果不为0就是非法)

  • exp:非法mask : 128.255.255.0
    m = 10000000 11111111 11111111 00000000
    (-m) = 01111111 00000000 00000001 00000000
    m & (-m) = 00000000 00000000 00000001 00000000
    m + (m & (-m)) = 10000001 00000000 00000000 00000000 (肯定不为0,因为1之间有0,无法一直进位)

  • exp: 特殊非法mask :255.255.255.255
    m + 1 == 0 就是这种情况

    #include <bits stdc++.h>
    using namespace std;
    int main() {
      ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
      uint32_t p[4], p1[4], p2[4];
      while (~scanf("%u.%u.%u.%u\n", p, p + 1, p + 2, p + 3)) {
          scanf("%u.%u.%u.%u\n", p1, p1 + 1, p1 + 2, p1 + 3);
          scanf("%u.%u.%u.%u\n", p2, p2 + 1, p2 + 2, p2 + 3);
          int8_t state = -1;
          uint32_t mk, ip1, ip2;
          int m;
          for (int i = 0; i < 4; i++) {
              if (p[i] > 255) state = 1;
              if (p1[i] > 255) state = 1;
              if (p2[i] > 255) state = 1;
              if (state == 1) goto nx;
          }
    
          for (int i = 0; i < 4; i++) {
              mk = (mk << 8) + p[i];
              ip1 = (ip1 << 8) + p1[i];
              ip2 = (ip2 << 8) + p2[i];
          }
          m = (int)mk;
          if (m + (m & (-m)) || !(m + 1)) {
              state = 1; goto nx;
          }
          if ((mk & ip1) == (mk & ip2)) state = 0;
          else state = 2;
      nx:
          printf("%d\n", state);
      }
      return 0;
    }