Skip to content

Commit 78756ea

Browse files
authored
Merge pull request cp-algorithms#1288 from ganeshvarbalaji/patch-3
Added a new section to bit-manipulation.md
2 parents b59e9d6 + 2b23aff commit 78756ea

1 file changed

Lines changed: 38 additions & 0 deletions

File tree

src/algebra/bit-manipulation.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,44 @@ int countSetBits(int n)
186186
}
187187
```
188188

189+
### Count set bits upto $n$
190+
To count the number of set bits of all numbers upto the number $n$ (inclusive), we can run the Brian Kernighan's algorithm on all numbers upto $n$. But this will result in a "Time Limit Exceeded" in contest submissions.
191+
192+
We can use the fact that for numbers upto $2^x$ (i.e. from $1$ to $2^x - 1$) there are $x \cdot 2^{x-1}$ set bits. This can be visualised as follows.
193+
```
194+
0 -> 0 0 0 0
195+
1 -> 0 0 0 1
196+
2 -> 0 0 1 0
197+
3 -> 0 0 1 1
198+
4 -> 0 1 0 0
199+
5 -> 0 1 0 1
200+
6 -> 0 1 1 0
201+
7 -> 0 1 1 1
202+
8 -> 1 0 0 0
203+
```
204+
205+
We can see that the all the columns except the leftmost have $4$ (i.e. $2^2$) set bits each, i.e. upto the number $2^3 - 1$, the number of set bits is $3 \cdot 2^{3-1}$.
206+
207+
With the new knowledge in hand we can come up with the following algorithm:
208+
209+
- Find the highest power of $2$ that is lesser than or equal to the given number. Let this number be $x$.
210+
- Calculate the number of set bits from $1$ to $2^x - 1$ by using the formua $x \cdot 2^{x-1}$.
211+
- Count the no. of set bits in the most significant bit from $2^x$ to $n$ and add it.
212+
- Subtract $2^x$ from $n$ and repeat the above steps using the new $n$.
213+
214+
```cpp
215+
int countSetBits(int n) {
216+
int count = 0;
217+
while (n > 0) {
218+
int x = std::bit_width(n) - 1;
219+
count += x << (x - 1);
220+
n -= 1 << x;
221+
count += n + 1;
222+
}
223+
return count;
224+
}
225+
```
226+
189227
### Additional tricks
190228
191229
- $n ~\&~ (n + 1)$ clears all trailing ones: $0011~0111_2 \rightarrow 0011~0000_2$.

0 commit comments

Comments
 (0)