Bitwise Operations was one of the most confusing topics for me at first. But once I started understanding how bits actually work, many CP problems suddenly became much easier to think about and optimize.
This blog is the result of a full day of grinding, where I tried to organize everything I know about bitwise tricks into a clear and structured form — from the basics to useful CP patterns. I tried to keep everything as simple and beginner-friendly as possible so that anyone can understand the core idea behind each trick instead of memorizing formulas. If even one trick from this blog helps someone solve a problem faster or understand bits more clearly, then this effort feels truly meaningful for me.
And finally, I want to express my deepest gratitude to Raha Ahmed for being The Strongest support in my CP journey. Her constant encouragement, belief and presence have played a huge role in shaping my progress and I’m truly grateful for everything she has done.
The Basics for Beginners :
Basics All - (click here)
Know The Bit
Binary is a number system that uses only two digits: 0 and 1. Each digit is called a bit. A binary number is just a way to represent a decimal number using powers of 2.
Binary : 1 0 1 0
Value : 8 4 2 1
Each position means a power of 2. If the bit is 1, we take that value. If the bit is 0, we ignore it.
So: 1010 = 8 + 2 = 10
and 1101 = 8 + 4 + 1 = 13
We usually read binary from right to left, starting from the 0th bit.
This is important because bitwise operations (AND, OR, XOR, NOT and Shifts) work directly on these bits instead of the decimal value. So if you understand binary properly, all bitwise tricks in CP become much easier to understand.
Watch for Better Idea :-
Bitwise AND (&)
Bitwise AND checks two bits one by one. The result becomes 1 only when both bits are 1. If any one of the bits is 0, the result becomes 0. You can simply think: both need to be 1.
Example :
1010
& 1001
------
1000
10 & 9 = 8
Bitwise OR (|)
Bitwise OR compares two bits one by one. If at least one bit is 1, the result becomes 1. Only 0 | 0 gives 0. You can simply think: one 1 is enough.
Example :
1010
| 1001
------
1011
10 | 9 = 11
Bitwise XOR (^)
Bitwise XOR checks whether two bits are different or not. If the bits are different, the result becomes 1. If both bits are same, the result becomes 0. You can simply think: different means 1.
Example :
1010
^ 1001
------
0011
10 ^ 9 = 3
Bitwise NOT (~)
Bitwise NOT flips every bit of a number. All 1 become 0 and all 0 become 1. It just changes every bit to its opposite value. This operation works on every bit individually.
Example :
~1010 = 0101
~10 = -11
Think => Why does this become negative ? info => ~n = -(n+1) but think How and Why ?
Left Shift (<<)
Left Shift moves all bits to the left by n positions. Every left shift usually multiplies the number by 2. More shifts mean a bigger value. New empty places on the right become 0.
Example 1 :
1010 << 1 = 10100
10 << 1 = 20
Example 2 :
0011 << 2 = 1100
3 << 2 = 12
Right Shift (>>)
Right Shift moves all bits to the right side one by one n times. Every right shift usually divides the number by 2 (integer / floor division). Bits on the right side are removed.
Example 1 :
1010 >> 1 = 0101
10 >> 1 = 5
Example 2 :
10100 >> 2 = 00101
20 >> 2 = 5
1 << x vs 1LL << x
When we write: 1 << x the value 1 is treated as an int. int usually stores up to 32 bits. So for very large shifts, the value can overflow and give wrong results.
But when we write: 1LL << x the 1LL becomes a long long. A long long can store up to 64 bits, so it is much safer for large shifts.
I directly use: 1LL << x to stay safe for large values.
For division by right shift there is a big gotcha. It would always work for unsigned int x, or for non-negative int. For negative ints it's up to implementation of compiler. In practice it's usually arithmetic shift, so 31th bit would be copied in every bit position shifted in from the left, so negative numbers remain negative. But then division result is not correct when it should result in zero. For example, (-3)>>2 would give not zero but -1. Anyway compilers would optimize division by constant power of two.
Yes, correct. For non-negative numbers, x >> k works like division by 2^k. But for negative integers, right shift behavior is implementation-defined in C++. Most compilers use arithmetic shift, so sign bits get copied. Example: (-3) >> 2 = -1 while -3 / 4 = 0
Thanks for mentioning this. The post was mainly written for beginners, so I tried to keep the explanations simple.
I checked your CF profile & you already have good potential. Just keep practicing consistently and focus on understanding patterns deeply. Hope to see you reach Specialist very soon, and even beyond that. Keep it up!
Truly impressive work... It's rare to find such a clear, well structured and concise explanation of bitwise tricks with examples. May your hard work pay off !!
Absolutely! That’s actually one of the cleanest way. If __builtin_popcount(n) == 1 then n is a power of 2. Just one thing to keep in mind — inside very tight loops n & (n - 1) is usually preferred in CP since it’s a direct bitwise operation and slightly faster.
Exactly, that was actually intentional. I wanted Part 1 to be fully beginner friendly for people who are completely new to bits and binary concepts. Part 2 will go into more intermediate-level tricks & the final part 3 will focus on the actual harder CP oriented ideas. Still, really glad you enjoyed it & liked.
Hey! I really liked this blog, been reading it since yesterday. I got to learn some really cool new things, and I really appreciate the effort you put into writing this. Also, this reminded me of another trick for setting the lowest unset bit which is x | (x + 1).
Always gonna be a fan of bit manipulation. I have replaced modulo with numbers which are power of 2 with bitwise AND which is x % 2^n = x & (2^n - 1). Heading to read the intermediate one now :)
Thanks man for reading and sharing these brilliant tricks :) using x | (x + 1)x & (2^n - 1) is great but just keep this in mind :-
1. For x | (x + 1) : Be careful if $$$x$$$ is already at its maximum value (INT_MAX) then x + 1 will cause a signed integer overflow.
2. For the Modulo Trick : This works perfectly only for positive numbers. Like :- -5 % 4 gives -1 but -5 & 3 will give 3 this might lead to a WA ! also dont forget to use proper parentheses due to operator precedence like x & ((1 << n) - 1).
Yeap, check there is a star button next to the voting button for this blog... click on the button, and this blog will be added to your favorite list. you will find the favourite list on you profile later.
This is massive man ! but insightful infos ! its actually in 2 parts first one is Gospers Hack & The second part is Combinatorial DP. Since you asked for an explanation of how this works - let me break down the first part (nssbn) :-
Gospers Hack (Next mask with the exact same number of set bits) :-
Lets understand how this $$$O(1)$$$ magic works line by line. Suppose our current mask is x = 22 (Binary: 010110). It has exactly 3 set bits. We want to find the next smallest number that also has exactly 3 set bits.
ll right = x & -x; This is our classic trick ! It extracts the lowest set bit (rightmost 1). For x = 010110, right becomes 000010.
ll higher = x + right; Adding right to x causes a carry ripple. It turns the rightmost continuous block of 1s into 0s and flips the next available 0 on the left to a 1. 010110 + 000010 = 011000. Great! we moved the block to the left ! But wait — in doing that we lost the remaining 1s from that block. We need to restore them, but place them as far right as possible to keep the number strictly the next smallest.
return higher | ((x ^ higher) / right) >> 2; This line does the exact mathematical cleanup to restore those lost 1s at the very end.
x ^ higher isolates the bits that changed (001110).
Dividing by right shifts these changed bits to the rightmost position.
>> 2 exactly trims out the extra bits caused by the carry, leaving us with the exact number of 1s we need to restore.
Finally, | merges our higher value with these adjusted 1s. Result: 011000 | 000001 = 011001 (which is 25). The Magic works flawlessly !
As for the second part (Lexicographical DP for finding the $$$K$$$-th next/prev mask) — to be honest that is still too hard for me ! I am still in the learning phase and havent mastered this kind of advanced combinatorial DP yet !
For division by right shift there is a big gotcha. It would always work for unsigned int x, or for non-negative int. For negative ints it's up to implementation of compiler. In practice it's usually arithmetic shift, so 31th bit would be copied in every bit position shifted in from the left, so negative numbers remain negative. But then division result is not correct when it should result in zero. For example, (-3)>>2 would give not zero but -1. Anyway compilers would optimize division by constant power of two.
Yes, correct. For non-negative numbers,
x >> kworks like division by2^k.But for negative integers, right shift behavior is implementation-defined in C++.
Most compilers use arithmetic shift, so sign bits get copied.
Example:
(-3) >> 2 = -1while-3 / 4 = 0Thanks for mentioning this. The post was mainly written for beginners, so I tried to keep the explanations simple.
are you auto infinity or what???
Na Bhai :)
it's actually
zero to infinityIt is well defined since C++20.
Yeap !
Nice Content
Thanks a lot. I am glad you liked the Content.
Great Content
Thanks a lot. I am glad that you found the Content useful.
thats almost 2 bites
Haha that was the goal actually :))
Helpful content
Thanks
more suggestions to increase accuracy and speed to solve bitwise operator questions? i struggle a lot in these type of questions
You should collect the Problems first then solve one by one. I tried this and it helps me the most.
https://codeforces.me/problemset?order=BY_RATING_ASC&tags=bitmasks%2C800-1400
Try to solve these problems of each rating from 800 to 1400.
thanks a lot hope so will reach specialist soon
I checked your CF profile & you already have good potential. Just keep practicing consistently and focus on understanding patterns deeply. Hope to see you reach Specialist very soon, and even beyond that. Keep it up!
Power of '0' & '1'
ig :)
Yeap :)
Updated !
Useful
Thank you.
cool blog. U got my like and comment to share up!
Thanks a lot ! Really appreciate the support :)
Truly impressive work... It's rare to find such a clear, well structured and concise explanation of bitwise tricks with examples. May your hard work pay off !!
Now it feels like all the effort was worth it :)
Your support makes all the hard work worth it & Now the blog feels complete !
<3
When we want to check if a number n is a power of 2, can we use the __builtin_popcount(n) function?
Absolutely! That’s actually one of the cleanest way.
If
__builtin_popcount(n) == 1thennis a power of 2.Just one thing to keep in mind — inside very tight loops
n & (n - 1)is usually preferred in CP since it’s a direct bitwise operation and slightly faster.Thanks for the tip about bitwise operation! Orz
You're welcome !
Thanks for the clean explanation. It was really helpful.
I am glad that you found the content useful.
wtf strong
Tried my best :)
Glad you liked it !
cmnting to save
Glad to hear!
This is a good binary blog.
But Part 1 is too too too too easy.....
orz
Exactly, that was actually intentional.
I wanted Part 1 to be fully beginner friendly for people who are completely new to bits and binary concepts.
Part 2 will go into more intermediate-level tricks & the final part 3 will focus on the actual harder CP oriented ideas.
Still, really glad you enjoyed it & liked.
Waiting for Advanced Part!!
one eternity later ! hahaha :)
Glad to know brother. coming soon inshaAllah.
I think The Next Part should be on Topics not just Tricks !
up
Glad you liked it !
Wow, Great content i was studying bits for a while,I just know some basics and this is helpful waiting for the next part
Glad you liked it.
I will publish it tonight or tomorrow !
Thanks a lot, really nice educational information for all levels :)
Youre Welcome ! Glad You Liked it !
Auto comment: topic has been updated by 0t0infinity (previous revision, new revision, compare).
Hey! I really liked this blog, been reading it since yesterday. I got to learn some really cool new things, and I really appreciate the effort you put into writing this. Also, this reminded me of another trick for setting the lowest unset bit which is
x | (x + 1).Always gonna be a fan of bit manipulation. I have replaced modulo with numbers which are power of 2 with bitwise AND which is
x % 2^n = x & (2^n - 1). Heading to read the intermediate one now :)Thanks man for reading and sharing these brilliant tricks :)
using
x | (x + 1)x & (2^n - 1)is great but just keep this in mind :-1. For
x | (x + 1): Be careful if $$$x$$$ is already at its maximum value (INT_MAX) thenx + 1will cause a signed integer overflow.2. For the Modulo Trick : This works perfectly only for positive numbers.
Like :-
-5 % 4gives-1but-5 & 3will give3this might lead to a WA ! also dont forget to use proper parentheses due to operator precedence likex & ((1 << n) - 1).is there a way to mark this blog for future reference? cause this is hella useful.
Yeap, check there is a star button next to the voting button for this blog... click on the button, and this blog will be added to your favorite list. you will find the favourite list on you profile later.
Glad you found it useful ! yeah man, to make it favorite -
follow the instructions in
RxSoul's comment.thanks ubub
RxSoulfor your help <3needed content thanks
glad you liked it man !
Thanks for this , bit problems were cooking me good. Now I can finally retaliate lol.
come on man lets cook like Heisenberg !
Mr. White is back in the kitchen !
yessir definitely
can u explain how this works
https://codeforces.me/blog/entry/82379?#comment-711091
This is massive man ! but insightful infos ! its actually in 2 parts first one is Gospers Hack & The second part is Combinatorial DP. Since you asked for an explanation of how this works -
let me break down the first part (
nssbn) :-Gospers Hack (Next mask with the exact same number of set bits) :-
Lets understand how this $$$O(1)$$$ magic works line by line. Suppose our current mask is
x = 22(Binary:010110). It has exactly 3 set bits. We want to find the next smallest number that also has exactly 3 set bits.ll right = x & -x;This is our classic trick ! It extracts the lowest set bit (rightmost 1).
For
x = 010110,rightbecomes000010.ll higher = x + right;Adding
righttoxcauses a carry ripple. It turns the rightmost continuous block of 1s into 0s and flips the next available 0 on the left to a 1.010110 + 000010 = 011000.Great! we moved the block to the left ! But wait — in doing that we lost the remaining 1s from that block. We need to restore them, but place them as far right as possible to keep the number strictly the next smallest.
return higher | ((x ^ higher) / right) >> 2;This line does the exact mathematical cleanup to restore those lost 1s at the very end.
x ^ higherisolates the bits that changed (001110).rightshifts these changed bits to the rightmost position.>> 2exactly trims out the extra bits caused by the carry, leaving us with the exact number of 1s we need to restore.|merges ourhighervalue with these adjusted 1s.Result:
011000 | 000001 = 011001(which is 25). The Magic works flawlessly !As for the second part (Lexicographical DP for finding the $$$K$$$-th next/prev mask) — to be honest that is still too hard for me ! I am still in the learning phase and havent mastered this kind of advanced combinatorial DP yet !
This really helped a lot. Thank you
Glad you found it helpful man !