洛谷P1555题解-Meet In Middle

洛谷P1555题解-Meet In Middle

原题:https://www.luogu.com.cn/problem/P1555

本人第一次写题解,讲得不好勿喷~

题目大概是说给定这个数转成二进制和三进制的结果
但是这两个结果是有问题的,每个结果会且只会错一位
最后让求这个数而十进制形式

二进制和三进制就是一个很鸡肋的东西
一是互相转不容易,二是二进制转成三进制后不是以为对一位或一位对多位,而是会错开
所以O1的解法可能有点难度
但注意到本题n仅为109,那位数就不会很多了
二进制大概30位,三进制会更少些
所以可以直接暴力搜索有问题的位。

接下来就是怎么暴力的问题
我在这里用了Meet In Middle的思想,即二进制和三进制同时搜索(不是并行,初始化二进制的时候可以先用哈希表存上,但由于可能变成的数很大,这里用了map<int, int>来优化),看有没有碰撞
然后改变当前的位就用+2(3)n就好了2(3)n可以跟着循环算,也可以预处理
还有一点注意的就是前导0

好了,附上代码。如有错误/优化/疑问 欢迎提出

// code by 于斯为盛
#include <iostream>
#include <map>

using namespace std;

int _num;
int _bin;//binary, 存储二进制数据 
int _ter;//Ternary, 存储三进制数据 
int _ans; 
string _curBin;//输入的二进制,因为位数太长,所以用long long 
string _curTer;//同理 
map<int, int> _list;//hash, 二进制可以变成的数,可以为 1,不可以为 0 

void ParseIn(){
  cin>>_curBin>>_curTer;
}

void StringToInt(){//把输入的string转成int 
  for(int i=0; i<_curBin.length(); i++){
    _bin*=2;
    _bin+=(int)_curBin[i]-'0';
  }

  for(int i=0; i<_curTer.length(); i++){
    _ter*=3;
    _ter+=(int)_curTer[i]-'0';
  }
}

void GenList(){//初始化_list, 即搜索二进制修改一位可以到达的数 
  int add=1;
  int cur;//当前位
  int num=_bin;
  for(int i=0; i<_curBin.length(); i++){//要考虑前导 0,下面同理 
    cur=num&1;
    if(cur){
      _list[_bin-add]=1;//如果当前位是 1,则将其改成 0 ps:_list[i]是哈希表,表示二进制是否可以变成 i 
    } 
    else{
      _list[_bin+add]=1;//如果当前位是 0,则将其改成 1 
    }
    num/=2;
    add*=2;
  }
}

void Research(){//查找三进制修改一位与二进制修改一位的交集 
  int add=1;
  int cur;//当前位
  int num=_ter;
  for(int i=0; i<_curTer.length(); i++){
    cur=num%3;
    num/=3;
    if(cur==0){//当前位是0,与前面同理 
      if(_list[_ter+add]){
		_ans=_ter+add;
		return;
      }
      if(_list[_ter+2*add]){
		_ans=_ter+2*add;
		return;
      }
      add*=3;
      continue;
    }

    if(cur==1){//当前位是1,与前面同理 
      if(_list[_ter-add]){
		_ans=_ter-add;
		return;
      }
      if(_list[_ter+add]){
		_ans=_ter+add;
		return;
      }
      add*=3;
      continue;
    }

	//当前位是2,与前面同理 
    if(_list[_ter-add]){
      _ans=_ter-add;
      return;
    }
    if(_list[_ter-2*add]){
      _ans=_ter-2*add;
      return;
    }
    add*=3;
  }
}

void Core(){
  StringToInt();
  GenList();
  Research();
}

void WriteOut(){
  cout<<_ans<<endl;
}

int main(){
  ParseIn();
  Core();
  WriteOut();
  return 0;
}

——by于斯为盛

猜你喜欢

转载自blog.csdn.net/maxChang_algha/article/details/106985419