Detailed solution to bit operation - 2018 CCPC Guilin station: D. Bits Reverse

Posted by daria on Sat, 15 Jan 2022 16:01:04 +0100

Bit operation problem solution

Question source: 2018 CCPC Guilin station: D. Bits Reverse

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