按照昨天的推导过程,今天把代码贴上:顺便提一下原文中(http://zhedahht.blog.163.com/blog/static/25411174201283084246412/)代码本身的算法却没错,按照代码本身的解法,上文蓝色字体部分(那么x^a、x^b、x^c的结果中,有一个或者三个数字的第m位是1),应改为那么f(x^a)、f(x^b)、f(x^c)的结果中,有一个或者三个数字的第m位是1。同样的,容易证得f(x^a)、f(x^b)、f(x^c)不可能三个都为1,所以f(x^a)、f(x^b)、f(x^c)只有其中一个为1,原文的代码正是基于这个结果写的。一下贴出按照昨天证明过程写的代码:
#include <iostream></span>
#include <vector>
#include <cassert>
#include <iterator>
#include <algorithm>
//#define DEBUG
using namespace std;
inline int makeOnlyLowestBit1On(const int n)
{
if(n==0)
return 0;
int result = 1;
for(;(result&n)==0;result<<=1)
;
return result;
}
inline bool isFixBitSame(int n_power_2,int number1,int number2)
{
return (n_power_2&number1) == (n_power_2&number2);
}
void findOnlyAppearOnceThreeNumber(const vector<int>& data_array,vector<int>&result)
{
int three_number_or=0;
//x = a^b^c (x=three_number_xor)
for(vector<int>::const_iterator iter = data_array.begin();iter!=data_array.end();++iter)
three_number_or ^= *iter;
//f(x^a)^f(x^b)^(x^c)
int diff_bit = 0;
for(vector<int>::const_iterator iter = data_array.begin();iter!=data_array.end();++iter){
#ifdef DEBUG
cout<<"diff_bit: "<<diff_bit<<endl;
#endif
diff_bit ^= makeOnlyLowestBit1On(three_number_or^*iter);
}
diff_bit = makeOnlyLowestBit1On(diff_bit);
#ifdef DEBUG
cout<<"diff_bit: "<<diff_bit<<endl;
#endif
assert(diff_bit!=0);
//cout<<"diff_bit:"<<diff_bit<<endl;
//find first number
int first_number=0;
for(vector<int>::const_iterator iter = data_array.begin();iter!=data_array.end();++iter){
if(isFixBitSame(diff_bit,three_number_or,*iter)){
#ifdef DEBUG
cout<<"iter: "<<*iter<<endl;
#endif
first_number ^= *iter;
}
}
result.push_back(first_number);
//find the other two numbers
int two_number_first_diff_bit = makeOnlyLowestBit1On(three_number_or^first_number);
int second_number = 0;
for(vector<int>::const_iterator iter = data_array.begin();iter!=data_array.end();++iter){
if((*iter!=first_number)&&((*iter&two_number_first_diff_bit)>0))
second_number ^= *iter;
}
result.push_back(second_number);
result.push_back(three_number_or^first_number^second_number);
#ifdef DEBUG
copy(result.begin(),result.end(),std::ostream_iterator<int>(std::cout," "));
std::cout<<std::endl;
#endif
}
int main(int argc,char *argv[])
{
int case_num;
vector<int> data,result;
while(cin>>case_num){
int value;
for(int i = 0;i<case_num;++i){
cin>>value;
data.push_back(value);
}
findOnlyAppearOnceThreeNumber(data,result);
copy(result.begin(),result.end(),std::ostream_iterator<int>(std::cout," "));
std::cout<<std::endl;
data.clear();
result.clear();
}
return 0;
}