0t0infinity's blog

By 0t0infinity, history, 5 months ago, In English

This is the Part-2 of my Bitwise Operations Blog. In this part, I focused more on intermediate-level bitwise tricks, Common CP Patterns and a few slightly advanced techniques that appear frequently in contest. — Part-1 — Click Here
I tried to explain the intuition and thinking process behind each trick as clearly and simple as possible.

And as always, Heartfelt thanks to Raha Ahmed for her endless encouragement, strongest support and constant belief in me !


Core Concepts You Must Understand First :-


Intermediate level Bitwise Problems in CP rarely ask you to just "check" or "set" a bit. Instead, they require you to use the Mathematical Properties of bits to optimize your code. Before we jump into the 8 Master Pattern, you need to firmly understand these 5 core concepts.
If you understand these the upcoming patterns will feels like magic !


Core Explanations - (click here)

Topic 1 : Bit-by-Bit Contribution :-


Explanation - (click here)

Topic 2 : The Equation That Solves Half of Bitwise Math :-


Explanation - (click here)

Topic 3 : The Monotonicity of AND / OR :-


Explanation - (click here)

Topic 4 : Greedy with MSB : Top-Down Approach :-


Explanation - (click here)

Topic 5 : Prefix XOR : The O(1) Range Query Magic :-


Explanation - (click here)

Topic 6 : Submask Enumeration : The Magic Loop :-


Explanation - (click here)

Topic 7 : __builtin_clz and __builtin_ctz Tricks :-


Explanation - (click here)

Topic 8 : Game Theory : The Magic of Nim-Sum :-


Explanation - (click here)


Part-3 (Advanced Bitwise Operations) :-

To be honest, I haven’t completely mastered the most advanced bitwise techniques yet and there is still so much left for me to learn.
So I plan to write a Part-3 in the future when I dive deeper into those advanced topics and feel truly capable of explaining them.
Please keep me in your prayers. Happy journey, Everyone ! Regards :- RS1630


  • Vote: I like it
  • +75
  • Vote: I do not like it

»
5 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Aha, Sprague-Grundy theorem for Div2B! That’s why it took me an hour to solve last div2B, because I didn’t know enough useless master level things!

Read the post before upvoting it.. this is slop

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

Really nice content!

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

Very helpful, thanks

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

Part 3 once you reach cm trust

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

Really Helpful. This topic is nightmare for me.

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

This content is extremely helpful, your effort behind writing this post is highly appreciated!

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

ubub <3

Such great content with simple explanations. This topic is terrible :)

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

In Topic 1, surely there's no carry but if we chose bit as 1 in say 3rd position then arent automatically other bits are decided too? as there are only certain numbers with third position as 1 and they have fixed value for other bits.

please clear my doubt!

  • »
    »
    5 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Good catch! Yes, the bits inside a specific number are fixed. But the magic here is that we arent tracking specific numbers anymore. We are just counting how many (1, 0) pairs exist in the 3rd column across the whole array, calculating their total value and adding it directly to the final sum ! clear brother ?

    • »
      »
      »
      5 months ago, hide # ^ |
       
      Vote: I like it +3 Vote: I do not like it

      no i am still confused, the third column represents 1,0 using the data of numbers only right, so if you chose 1 then corresponding to that why arent other bits fixed?

      • »
        »
        »
        »
        5 months ago, hide # ^ |
         
        Vote: I like it 0 Vote: I do not like it

        I get your point! Yes, if you look at a specific 1 in the 3rd column, its other bits are fixed to its originsl number. But we dont care about the other bits at that moment. Because addition is commutative, instead of doing Number1 + Number2, we are doing -
        (Sum of all 1st bits) + (Sum of all 2nd bits) + (Sum of all 3rd bits)
        When we calculate the 3rd column's total, we ignore the 2nd column because we will calculate the 2nd column's total entirely separately ! now clear ?

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

thanks, very helpful

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

very nice blog, enjoyed reading it and also learnt a few new things, that binary search idea in 3rd section was gr8 too, thanks for the blog, cant wait for the part3!

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

It's Easy too.

Hope for Part 3 ;>

»
5 months ago, hide # |
← Rev. 3  
Vote: I like it +3 Vote: I do not like it

W content, Loved the Game Theory Part (Nim Sum). (+1) Interested for Part-3!

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

loved it...!❤️

»
5 months ago, hide # |
 
Vote: I like it +9 Vote: I do not like it

Regarding topic 7, consider using the C++ bit manipulation header. This gives you a number of very useful operations, such as the ones mentioned above. Really just read through each operation and I swear your bit manipulation problems will become that much easier/nicer to implement :)

A nice plus from these functions is that:

  • C++ automatically deduces the implementation for each function based on the provided type, so you don't have to worry about putting the lls as the suffix.
  • Also, you're forced to used unsigned types. While this might seem annoying to some, in reality it's very good for type safety. This is due to the fact that when we do bit problems, we generally envision manipulating masks that map on to some non negative integer. So, if that invariant is ever broken we can get unexpected results (well, if we're doing something finicky, which happens a lot in bit manipulation problems).
  • You get more functions! So instead of having to do 1LL << (31 - __builtin_clz(x)), you can just put bit_floor(x) and it works!!! This feature can be used to trivially initialize segment trees. So instead of having to do something like len=1<<(31-__builtin_clz(2*n-1)) to initialize the base length of the segtree, you can just put bit_ceil(x) and that's it! Notice that this point also helps with "code safety", as you have to write less janky code which is easy to mess up.

As a separate note, I really recommend reading through the C++ reference (on cppreference), as you can learn about a number of functions/data structures that are basically just "Quality of Life" features. A few examples:

  • Too lazy to write a two pointers to merge two sets? Use std::merge.
  • Too lazy to write a two pointers to get the intersection of two sets? Use std::set_intersection
  • Need a way to store not necessarily unique sorted items which reference other values? Use std::multimap (I haven't seen a lot of people use it, and some problems are just nicer to implement with this, although of course you could use a multiset which would be a bit slower...)
  • Want to iterate over a map in reverse without having to use explicit reverse iterators? Just do for (auto &[k, v] : your_map | std::views::reverse) { ... }
  • Need to sort your elements in a stable manner (ie, if two elements are equal then they maintain their original relative ordering)? Just use std::stable_sort
  • And so much more
  • »
    »
    5 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Damn Man !!! This is super helpful. I hated writing that ugly __builtin_clz() for seg trees.
    The <bit> header looks way better. Great tips — Thanks a lot !

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

Well done very good blog ;)))

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

I think learning a theory is better when you have a lot of practice problems regarding about the topic to quickly catch the topic and master it . so , I would like to thanks you first and give a suggestion to add problem list or link of list which contains problems < Thanks a lot!

  • »
    »
    5 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Thanks man ! Thats a great suggestion & I actually thought about it. But finding the perfect practice problems for each topic takes a ton of time & I couldnt manage it this time but ill definitely keep this in mind & try to add a list later on !

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

Thanks for sharing 0t0infinity :)

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

Very well made, I needed to create some notes to quickly get the function, instead of coming up with the approach every single time. Thanks.

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

wtf strong

»
5 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

great work (begineer part was also good). btw congratulations on reaching expert

»
5 months ago, hide # |
← Rev. 2  
Vote: I like it +3 Vote: I do not like it

What an amazing blog! we want more like these. Whomever I share it with, loved it.

However could you also explain the reason/proof behind the nim-sum being 0 is same as empty game state?

  • »
    »
    5 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Tahnks Man ! Really glad you liked it !
    An empty game state means all piles are 0, so the XOR sum is naturally 0. But logically an empty board just means you have no moves left to win. A Nim-sum of 0 is the exact same trap ! If the sum is 0, ANY move you make will instantly turn it non-zero. You are basically forced to hand a winning board right back to your opponent.
    So, a Nim-sum of 0 is basically a trap. Whether the board is completely empty or the sum is 0 in both cases, you have zero good moves left and youre stuck. Hope this helps !