解题思路:模拟,位运算的使用真的很完美,我写了两小时,无法AC,但看到别人写的,受益匪浅。
把各IP地址存入无符号整型中,由于无符号整型恰好32位刚好能存完一个IP地址,再用上位运算,比较IP地址不同的部分,便可得出。转载自https://blog.youkuaiyun.com/to_be_better/article/details/49969061
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
unsigned int num[1005]={};///32bit
int main(){
int n;
while(cin>>n){
memset(num,0,sizeof(num));
for(int i=0;i<n;i++){
char t[40];
cin>>t;
int c=0;
for(int j=0;j<strlen(t);j++){
if(t[j]=='.'){
num[i]=(num[i]<<8)+c;
c=0;
}
else{
c=c*10+t[j]-'0';
}
}
num[i]=(num[i]<<8)+c;
}///把多个网络地址存至无符号数组中
unsigned int ans=~0,tt;///~0 即取反32位全为1,(其中ans记录最后得到的是子网掩码)
for(int i=1;i<n;i++){
unsigned int q=num[i]^num[0];///各IP地址中位数不相同的部分,必定是要消去的,才能得到最小值
while(q){
ans&=~(q|(q-1));///把末尾连续的0变为1,再取反为0,即是把num[i](多个)中取出含有0的位数变为0
q=q&(q-1);///把末尾第一个为1的变为0
}
}
tt=ans&num[0];
int sans[4]={};
int pos=0;
while(tt!=0){
sans[pos++]=tt%(1<<8);
tt>>=8;
}//sans[]记录处理过后网络地址的值
for(int i=3;i>=0;i--){
cout<<sans[i];
if(i)
cout<<".";
}
cout<<endl;
pos=0;
memset(sans,0,sizeof(sans));
while(ans!=0){
sans[pos++]=ans%(1<<8);
ans>>=8;
}
for(int i=3;i>=0;i--){
cout<<sans[i];
if(i) cout<<".";
}
cout<<endl;
}
return 0;
}