Let’s just start with a problem.
Problem 1. Alice has hidden balls numbered from to . Exactly two of them, numbered and , are colored red and the rest are white. Bob needs to report Alice a set of 18 pairs of sets, such that and for . Bob wins if such that or , that is and are in different sets of the same pair. You need to construct the set for Bob.
Solution. There’s an easy probabilistic solution to it. Randomly choose integers and put them in , put the rest of them in . Now the probability of and to fall in the same set is around , so if we continue doing the same for , our probability of success becomes around , which is very close to . But we want a deterministic solution, and that’s where our trick comes in.
The trick: The whole idea can be wrapped up in one line: Place all integers with the -th bit turned off in and the rest in . Formally, let denote the -th bit of , where . For all , set and . And it magically solves the problem! How? Well, since , where (that is, their -th bits differ). That means both and cannot be in the same set- one of them must be in and the other must be in . Since , the bit they differ at will always be smaller than .
That’s it! This idea of partitioning into disjoint sets based on bits comes in handy in many interactive problems.
Well, I first saw this trick in a shortest path problem, which was probably like this:
Problem 2. You are given a weighted graph , and a set of special nodes. You need to find , where is the shortest distance from node to .
Solution. This problem does have a solution which requires some observations if I remember correctly. But the bit trick gives us a very simple solution.
If we choose a set and run multisource Dijkstra from nodes in , we find the shortest path from all to . If and are the closest pair of nodes in , and if we can somehow put one of them in the source nodes and the other in the destination nodes, we will get the shortest pair distance! The bit trick will do that for us. We will run multisource Dijkstra. During the -th time, set and run Dijkstra from the nodes in . Like the last time, since , such that , one of them will be in the source nodes and the other will be in the destination nodes, giving us the shortest pair distance!
Problem 3. (CEOI16 ICC) There’s a hidden graph of nodes. Initially, the graph has no edges. Until the graph becomes connected, the Terran will add an edge such that and were previously disconnected (so, total edges will be added, eventually forming a tree). After adding each edge, we will have to find out and . Allowed Query: Given two disjoint sets of nodes, computer will return whether there exists such that and are connected directly by an edge. You can ask at most queries overall.
Solution. We will solve this for one edge only, as we can repeat the same algorithm for the rest of them. If there are currently components, with the bit trick, we can find two sets such that and in queries. Pick one node from each component (preferably the representative node if you use DSU to maintain the graph), and apply the bit trick (well, before querying, don’t forget to push the other nodes of the components to their respective set as well). Now binary search on and find . Do the same for . (I skipped some details, I’m sure you can figure it out :D). This solution takes around queries per edge. I got 90 with this solution. However, after I checked the bits in random order while partitioning the representative nodes and ended the loop as I already found a valid division, I got 100. (This is another useful trick, often try randomizing things and see if it helps :D)
Here’s another nice problem, almost copy-pasted from Mamnoon Siam’s Note.
Problem 4. (The penguin’s game) There’s a hidden array a (size is at most ). Computer has selected two indices and such that and . Find using at most 19 queries. Allowed Query: given a set , computer returns (that is, the bitwise xor of all integers in ).
Solution. Well, binary search won’t work here. Note that If we ask with a set , we can deduce the parity of the number of in . So, using our trick we can determine which bits of and are the same and which aren’t. For that, for every bit , we can simply put all integers with -th bit on in and see if there are even numbers of in it. If so, the -th bit of them are equal; otherwise not. Now, if we can somehow find one of them, we have the necessary information to determine the other one, and we are done. Since , they will differ at least in one bit. So, we have a set of indices where exactly one of or lies. Find where that is using binary search. Also, this set’s size is at most half of the original array’s- that saves one query in binary search.
Problem 5. (POI Remont) You are given a color scheme ( for vertical strips of a wall ( is the color of the -th strip). A roller can paint two consecutive strips. You have total rollers, one for each pair of colors. You can use each roller at most once and each strip can be colored multiple times, but with the same color every time. Determine whether it is possible to complete the color scheme.
Solution. Construct a new array of pairs of colors (or rollers) of length and set . Obviously, we need to color the strips using the pairs from . Let denote whether we used the -th roller or not. It is easy to see both and cannot be for any , otherwise there is no way you can color the -th strip with color . We can actually write this condition in CNF form: This leads us to the well-known 2-SAT problem, but we have to add some additional conditions. First of all, and must be true since there’s no other way to color the first and last strip. Then comes the main challenge: since each roller can be used at most once, for each unique roller , we’ll have a set , and there can be at most one such that , and for all must be . But how to force this condition in 2-SAT?
To exist atmost one such that is true, must be true for all valid . But that leads us to new edges in our implication graph, which is too slow. And once again, the bit trick saves us!
Note that means and . But since adding these edges among all pairs is costly, we will add two layers of dummy nodes ( nodes in each layer) in the implication graph. Let’s denote them by and . Now for all , for each bit , add two directed edges: and (here is the -th bit of ). Now, since for all , there exists a bit in which they differ, and edges exist in the graph (here is a node from the dummy layer). That means and implications are added for all , which is all we needed!