Bit operation problem solution
Question source: 2018 CCPC Guilin station: D. Bits Reverse
Title Description
Topic meaning understanding
input T T T groups of data, each group of data contains two integers x , y x,y x. Y, when expressed as binary, carry out the inversion operation of three consecutive bits, for example ( 0 , 0 , 1 ) (0,0,1) (0,0,1) reverse to ( 1 , 0 , 0 ) (1,0,0) (1,0,0) ; After at least several inversion operations, the inverted integer can be obtained x , y x,y x. Y is equal; Output the minimum number of anti alignment times. If there is no solution, output − 1 -1 −1.
The data range is: T [ 1 , 1 0 4 ] T \ [1,10^4] T [1,104], x , y [ 1 , 1 0 18 ] x,y \ [1,10^{18}] x,y [1,1018]
The output format is: C a s e 1 : − 1 Case \quad 1: \quad -1 Case1:−1
Principle analysis
First of all, the essence of inversion operation is interlaced exchange, which has the following properties:
- Reverse switching has no effect on the median at all.
- In the inversion exchange, the adjacent bits are independent of each other, and the number of inversion steps can be calculated respectively by odd and even bits.
Secondly, make it clear x , y x,y x. Y conditions for equality after the minimum number of reversals:
- x , y x,y x. On y parity spacer 1 1 1 the numbers are equal.
- x , y x,y x. On y parity bit 1 1 1 reversely moves to the nearest parity bit of the other party.
Therefore, the general idea is to judge first x , y x,y x. Spacing on y binary bits 1 1 1 whether the quantity is equal or not. If it is not equal, it can be directly negated. When it is equal, the operation of inversion times shall be carried out. During the operation, pay attention to reversing to the nearest bit * and moving to equal.
code implementation
The boundary is limited to, T [ 1 , 1 0 4 ] T \ [1,10^4] T [1,104], x , y [ 1 , 1 0 18 ] x,y \ [1,10^{18}] x,y [1,1018] :
- T T T : i n t int int
- x , y x,y x,y : l o n g l o n g i n t long \ long \ int long long int
Start with two v e c t o r vector vector record separately x , y x,y x. In Y 1 1 If the number and position of 1 are different, it is directly negative:
#include <bits/stdc++.h> #Define lowbit (x) (X & - x) / / macro defines lowbit operation typedef long long LL; //Define long long data type using namespace std; LL T,res; //Define the number of global variable groups T result res //Bit operation function bool move (LL, x, ll, y) //Record the result of inversion times in res and return whether it can be performed bool move(LL x,LL y) { vector<LL> a,b; //Open two vector s to record the number and position of 1 in X and y if(!x||!y) return false; //If x,y has 0, it's negative while(x&&y) { // lowbit splits the position of each 1 of X and y LL ta=lowbit(x); LL tb=lowbit(y); x=x-ta; y=y-tb; // Which bit of each 1 is push ed in the vector LL cnta=0,cntb=0; while(ta) { ta=ta>>1; cnta++; } while(tb) { tb=tb>>1; cntb++; } a.push_back(cnta); b.push_back(cntb); //If one of X and Y becomes 0 first, it means that the number of 1 in X and Y is different, which is directly negative //If x and Y become 0 at the same time, the cycle ends normally from the cycle condition while (X & & Y) if(x==0||y==0) { if(x==y) break; else return false; } } // bool move ...
Without triggering a negative condition, two
v
e
c
t
o
r
vector
It has been recorded in the vector
x
,
y
x,y
x. Each of Y
1
1
1, and then calculate the minimum number of inversion operations; Because the minimum condition is the nearest neighbor bit, you can pair the two first
v
e
c
t
o
r
vector
vector sorts in ascending order, and then takes any number as the target, and operates the low to high position of another number to move to the low to high position of the target bit respectively. In the process of moving, it can not only ensure the minimum overall shift, but also show the parity bit if any bit cannot be moved to the target bit
1
1
If the number of 1 is not equal, it can be directly denied:
// bool move... res=0; //Reset result //Take vector a as the target, operate vector b, and record the minimum number of operations res for(auto i=a.begin();i!=a.end();i++) { LL c=0; for(auto j=b.begin();j!=b.end();j++) { LL t=abs(*i-*j); if(t%2!=0) continue; //If the difference between two 1 bits is not a multiple of 2, it cannot be reached by interlacing b.erase(j); //When the reachable bit is found, eliminate a target and record the switch c c=1; res=res+(t>>1); //res cumulative record inversion times break; } if(c==0) return false; //If the target bit cannot be found, it indicates that parity bit 1 is not equal and is directly negative } return true; //When the negative condition is not triggered, record the result res and return the true value }
Finally, when conditions are feasible, r e s res res records the minimum number of operations and returns t r u e true true, otherwise return f a l s e false false and output − 1 -1 −1;
The complete code is as follows:
#include <bits/stdc++.h> #Define lowbit (x) (X & - x) / / macro defines lowbit operation typedef long long LL; //Define long long data type using namespace std; LL T,res; //Define the number of global variable groups T result res //Bit operation function bool move (LL, x, ll, y) //Record the result of inversion times in res and return whether it can be performed bool move(LL x,LL y) { vector<LL> a,b; //Open two vector s to record the number and position of 1 in X and y if(!x||!y) return false; //If x,y has 0, it's negative while(x&&y) { // lowbit splits the position of each 1 of X and y LL ta=lowbit(x); LL tb=lowbit(y); x=x-ta; y=y-tb; // Which bit of each 1 is push ed in the vector LL cnta=0,cntb=0; while(ta) { ta=ta>>1; cnta++; } while(tb) { tb=tb>>1; cntb++; } a.push_back(cnta); b.push_back(cntb); //If one of X and Y becomes 0 first, it means that the number of 1 in X and Y is different, which is directly negative //If x and Y become 0 at the same time, the cycle ends normally from the cycle condition while (X & & Y) if(x==0||y==0) { if(x==y) break; else return false; } } res=0; //Reset result //Take vector a as the target, operate vector b, and record the minimum number of operations res for(auto i=a.begin();i!=a.end();i++) { LL c=0; for(auto j=b.begin();j!=b.end();j++) { LL t=abs(*i-*j); if(t%2!=0) continue; //If the difference between two 1 bits is not a multiple of 2, it cannot be reached by interlacing b.erase(j); //When the reachable bit is found, eliminate a target and record the switch c c=1; res=res+(t>>1); //res cumulative record inversion times break; } if(c==0) return false; //If the target bit cannot be found, it indicates that parity bit 1 is not equal and is directly negative } return true; //When the negative condition is not triggered, record the result res and return the true value } int main() { cin.tie(0); sync_with_stdio(false); cin>>T; for(LL i=1;i<=T;i++) { LL x,y; cin>>x>>y; if(move(x,y)) cout<<"Case "<<i<<": "<<res<<endl; else cout<<"Case "<<i<<": "<<-1<<endl; } return 0; }
Summary
Breakthrough: the essence of three bit inversion is interlaced exchange
Error prone point: the data range must be $long \ long \ int$
Template point: bit operation template l o w b i t lowbit lowbit split