题目: 可以用一个网络地址和一个子网掩码描述一个子网(即连续的IP地址范围)。其中子网 掩码包含32个二进制位,前32-n位为1,后n位为0,网络地址的前32-n位任意,后n位为0。 所有前32-n位和网络地址相同的IP都属于此网络。
例如,网络地址为194.85.160.176(二进制为11000010|01010101|10100000|10110000), 子网掩码为255.255.255.248(二进制为11111111|11111111|11111111|11111000),则该子网 的IP地址范围是194.85.160.176~194.85.160.183。输入一些IP地址,求最小的网络(即包含IP 地址最少的网络),包含所有这些输入地址。
例如,若输入3个IP地址:194.85.160.177、194.85.160.183和194.85.160.178,包含上述3 个地址的最小网络的网络地址为194.85.160.176,子网掩码为255.255.255.248
链接: https://vjudge.net/problem/UVA-1590
解:二进制的使用
每个ip有4个数字,从左开始找到第一个数字不是所有ip都一样,转化为8位二进制
从左数,到哪一位二进制码不同,记为mark;则对于地址是mark前与原码相同,mark后都为0,而对于子网掩码是mark前都为1,mark 后都为0
有个非常巧妙的方法求地址,就是 地址 = mask & 原码值;
#include<bits/stdc++.h>
using namespace std;
int f[9] = {255, 254, 252, 248, 240, 224, 192, 128, 0};
int ip[4][1024],s[4],ans[4];
int m;
int main()
{
while(~scanf("%d",&m))
{
memset(ip, 0, sizeof(ip));
for(int i = 0; i < m; ++i)
scanf("%d.%d.%d.%d",&ip[0][i],&ip[1][i],&ip[2][i],&ip[3][i]);
for(int i = 0; i < 4; i++)
{
int dif = 0, x, j;
int p,q;
sort(ip[i], ip[i] + m);
p = ip[i][m - 1];
q = ip[i][0];
for(j = 1; j <= 8; j++)
{
if(p % 2 != q % 2) dif = j;
p /= 2;
q /= 2;
}
s[i] = f[dif];
ans[i] = ip[i][0] & s[i];
}
for(int i = 0; i < 4; ++i)
if(s[i] != 255)
{
for(int j = i + 1; j < 4; j++)
{
s[j] = 0;
ans[j] = 0;
}
break;
}
printf("%d.%d.%d.%d\n",ans[0], ans[1], ans[2], ans[3]);
printf("%d.%d.%d.%d\n",s[0], s[1], s[2], s[3]);
}
return 0;
}