Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I try to solve some problems in a online website. And I've a solved a problem with simple C++ it worked well but it sometime throw a "Time limit exceeded" error. How to get rid of this?
Here is the question that I solved
There are two integers A and B. You are required to compute the bitwise AND amongst all natural numbers lying between A and B, both inclusive.
Here is my code.
#include<iostream>
using namespace std;
int main()
{
int t,a,b;
long ans;
cin>>t;
while(t--)
{
cin>>a>>b;
ans=a;
for(int i=a+1; i<=b; i++)
{
ans=ans&i;
}
cout<<ans<<endl;
}
}
If you have two numbers, X and Y, they are represented by a finite sets of bits:
X = Bx(1), ..., Bx(n)
and
Y = By(1), ..., By(n)
The bitwise AND between the two can be computed as
X ^ Y = (Bx(1) ^ By(1)), ..., (Bx(n) ^ By(n))
A B A ^ B
0 0 0
0 1 0
1 0 0
1 1 1
We observe that:
all the bits can be computed separately, we have as many equations as many bits
in a sequence of logical statements, where AND is the operator, the result is 0 if and only if ANY of the items is 0
So, if any numbers are pair, then the last bit is 0. Otherwise, the last bit will be 1. If any number will have a 0 as the penultimate bit, then the result for that bit will be 0. Otherwise it will be 1.
As a general rule, based on the pigeonhole principle, proposed by Dirichlet, if you have enough consecutive (elements) for a given bit, then the result for that bit will be 0. For example, for the very last bit you have two variations, therefore, if you have at least two numbers in your consecutive set, then the last bit will be 0. If we take the very next bit, then you have four variations: 00, 01, 10 and 11. So, if you have at least 3 numbers in your consecutive set, then this bit is 0. For the next bit, you have 8 variations: 000, 001, 010, 011, 100, 101, 110, 111. So, if you have at least 5 numbers in your consecutive set, then this bit is 0.
Now, since we have a simple rule that determines most bits if there are many items, you will end up with a few bits that exceed in their number of variations the rule I have described above. For those bits you can check the first and the last number. If they have the same value for that bit, then that value will be the result, be it 0 or 1.
Related
std::bit_width finds minimum bits required to represent an integral number x as 1+floor(log(x))
Why does std::bit_width return 0 for the value 0? Shouldn't it return 1, Since the number of bits required to represent 0 is 1?
Also, I think the 1 in the formula is an offset.
There is a strange bit of history to bit_width.
The function that would eventually become known as bit_width started life as log2, as part of a proposal adding integer power-of-two functions. log2 was specified to produce UB when passed 0.
Because that's how logarithms work.
But then, things changed. The function later became log2p1, and for reasons that are not specified was given a wider contract ("wide contract" in C++ parlance means that more stuff is considered valid input). Specifically, 0 is valid input, and yields the value of 0.
Which is not how logarithms work, but whatever.
As C++20 neared standardization, a name conflict was discovered (PDF). The name log2p1 happens to correspond to the name of an IEEE-754 algorithm, but it's a radically different one. Also, functions in other languages with similar inputs and results use a name like bit_length. So it was renamed to bit_width.
And since it's not pretending to do a logarithm anymore, the behavior at 0 can be whatever we want.
Indeed, the Python function int.bit_length has the exact same behavior. Leading zeros are not considered part of the bit length, and since a value of 0 contains all leading zeros...
Because mathematically it makes sense:
bit_width(x) = log2(round_up_to_nearest_integer_power_of_2(x + 1))
bit_width(0) = log2(round_up_to_nearest_integer_power_of_2(0 + 1))
= log2(1)
= 0
To elaborate what was said in the comments:
Assume "bit width" means "least number of bits required to store the (nonnegative integer) number". Intuitively we need at least log2(n) bits rounding up, so it is a formula close to ceil(log2(n)), so 255 would require ceil(log2(255)) = ceil(7.99..) = 8 bits, but this doesn't work for powers of 2, so we can add a fudge factor of 1 to n to get ceil(log2(n+1)). This happens to be mathematically equivalent to 1+floor(log2(n)) for positive n, but log2(0) is not defined or defined as something unuseful like negative infinitiy in the floor version.
If we use the ceiling formula for 0, we get the result. You can also see I didn't write out leading zeros, and as Nicol Bolas points out, 0 is all leading zeros.
n
bin(n)
bit_width(n)
8
1000
4
7
111
3
6
110
3
5
101
3
4
100
3
3
11
2
2
10
2
1
1
1
0
0
I found an observation by testing in C++.
Observation is ,
1 ) If two numbers where both numbers have odd number of set bits in it then its XOR will have even number of set bits in it.
2 ) If two numbers where both numbers have even number of set bits in it then its XOR will have even number of set bits in it.
1 ) If two numbers where one number has even number of set bits and another has odd number of set bits then its XOR will have odd number of set bits in it.
I could not prove it. I want to prove it. Please help me.
Code that i executed on my computer is
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int> vec[4];
for(int i=1;i<=100;i++){
for(int j=i+1;j<=100;j++){
int x=__builtin_popcount(i)%2;
int y=__builtin_popcount(j)%2;
int in=0;
in|=(x<<1);
in|=(y<<0);
int v=__builtin_popcount(i^j)%2;
vec[in].push_back(v);
}
}
for(int i=0;i<4;i++){
for(int j=0;j<vec[i].size();j++) cout<<vec[i][j] << " ";
cout << endl;
}
return 0;
}
It gives me
100 zeros in first line
100 ones in second line
100 ones in third line
100 zeros in fourth line
If there is a doubt in understanding the code then please tell me in comments.
This behavior mirrors an easy-to-prove arithmetical fact:
When you add two odd numbers, you get an even number,
When you add two even numbers, you get an even number,
When you add an odd number to an even number, you get an odd number.
With this fact in hand, consider the truth table of XOR, and note that for each of the four options in the table ({0, 0 => 0}, {0, 1 => 1}, {1, 0 => 1}, {1, 1, => 0}) the odd/even parity of the count of 1s remains invariant. In other words, if the input has an odd number of 1s, the output will have an odd number of 1s as well, and vice versa.
This observation explains why you observe the result: XORing two numbers with the counts of set bits of N and M will yield a number that has the same odd/even parity as N+M.
Thanks all who tried to answer.
We can give proof like this,
Suppose N is number of set bits in first number and M is set bits in second number.
Then set bits in XOR of these two numbers is N+M - 2 (Δ) where is delta is total number of bit positions where both of numbers have set bit. Now this expression explains every thing.
even + odd - even = odd
odd + odd - even = even
even + even - even = even
xor just clears out common bits. It doesn't matter how many bits are set, just how many bits are common.
With all bits common, the result is zero. With no bits in common, the result is the sum of set bits.
No conclusions based on parity of inputs unless you also account for parity of common bits.
A possible proof is based in the observation that xor is a conmutative opperator, so (xor digits of x) xor (xor digits of y) = xor of digits of (x xor y)
After searching the net I came to know that the bit-wise version of the sieve of eratosthenes is pretty efficient.
The problem is I am unable to understand the math/method it is using.
The version that I have been busy with looks like this:
#define MAX 100000000
#define LIM 10000
unsigned flag[MAX>>6]={0};
#define ifc(n) (flag[n>>6]&(1<<((n>>1)&31))) //LINE 1
#define isc(n) (flag[n>>6]|=(1<<((n>>1)&31))) //LINE 2
void sieve() {
unsigned i, j, k;
for(i=3; i<LIM; i+=2)
if(!ifc(i))
for(j=i*i, k=i<<1; j<LIM*LIM; j+=k)
isc(j);
}
Points that I understood (Please correct me if I am wrong):
Statement in line 1 checks if the number is composite.
Statement in line 2 marks the number 'n' as composite.
The program is storing the value 0 or 1 at a bit of an int. This tends to reduce the memory usage to x/32. (x is the size that would have been used had an int been used to store the 0 or 1 instead of a bit like in my solution above)
Points that are going above my head as of now :
How is the finction in LINE 1 functioning.How is the function making sure that the number is composite or not.
How is function in LINE 2 setting the bit.
I also came to know that the bitwise sieve is timewise efficient as
well. Is it because of the use of bitwise operators only or
something else is contributing to it as well.
Any ideas or suggestions?
Technically, there is a bug in the code as well:
unsigned flag[MAX>>6]={0};
divides MAX by 64, but if MAX is not an exact multiple of 64, the array is one element short.
Line 1: Let's pick it apart:
(flag[n>>6]&(1<<((n>>1)&31)))
The flag[n>>6] (n >> 6 = n / 64) gives the 32-bit integer that holds the bit value for n / 2.
Since only "Odd" numbers are possible primes, divide n by two: (n>>1).
The 1<<((n>>1)&31) gives us the bit corresponding to n/2 within the 0..31 - (& 31 makes sure that it's "in range").
Finally, use & to combine the value on the left with the value on the right.
So, the result is true if element for n has bit number n modulo 32 set.
The second line is essentially the same concept, just that it uses |= (or equal) to set the bit corresponding to the multiple.
This question already has answers here:
n & (n-1) what does this expression do? [duplicate]
(4 answers)
Closed 6 years ago.
I need some explanation how this specific line works.
I know that this function counts the number of 1's bits, but how exactly this line clears the rightmost 1 bit?
int f(int n) {
int c;
for (c = 0; n != 0; ++c)
n = n & (n - 1);
return c;
}
Can some explain it to me briefly or give some "proof"?
Any unsigned integer 'n' will have the following last k digits: One followed by (k-1) zeroes: 100...0
Note that k can be 1 in which case there are no zeroes.
(n - 1) will end in this format: Zero followed by (k-1) 1's: 011...1
n & (n-1) will therefore end in 'k' zeroes: 100...0 & 011...1 = 000...0
Hence n & (n - 1) will eliminate the rightmost '1'. Each iteration of this will basically remove the rightmost '1' digit and hence you can count the number of 1's.
I've been brushing up on bit manipulation and came across this. It may not be useful to the original poster now (3 years later), but I am going to answer anyway to improve the quality for other viewers.
What does it mean for n & (n-1) to equal zero?
We should make sure we know that since that is the only way to break the loop (n != 0).
Let's say n=8. The bit representation for that would be 00001000. The bit representation for n-1 (or 7) would be 00000111. The & operator returns the bits set in both arguments. Since 00001000 and 00000111 do not have any similar bits set, the result would be 00000000 (or zero).
You may have caught on that the number 8 wasn't randomly chosen. It was an example where n is power of 2. All powers of 2 (2,4,8,16,etc) will have the same result.
What happens when you pass something that is not an exponent of 2? For example, when n=6, the bit representation is 00000110 and n-1=5 or 00000101.The & is applied to these 2 arguments and they only have one single bit in common which is 4. Now, n=4 which is not zero so we increment c and try the same process with n=4. As we've seen above, 4 is an exponent of 2 so it will break the loop in the next comparison. It is cutting off the rightmost bit until n is equal to a power of 2.
What is c?
It is only incrementing by one every loop and starts at 0. c is the number of bits cut off before the number equals a power of 2.
This question already exists:
Closed 10 years ago.
Possible Duplicate:
c++ program to find total numbers of integers containing different digits
Suppose i have a unsigned integer, call it low and one another call it high such that high>low. The problem is to find integers which contains distinct digits over this range. For example, suppose low is 1 and high is 10 then the answer is 10, because all the numbers in this range contains distinct digits. If suppose low is 1 and high is 12, then the answer is 10, because 11 contains same digits.example 123,234,4567 is valid number but 121,2342,4546 is invalid number.I am not looking for a bruteforce algo., if anyone has a better solution then a usual bruteforce approach, please tell..
I would derive an algorithm to determine the number of such digits from 0-n, then you could simply compute (# of valid numbers 0-high) - (# of valid numbers 0-low). To get the valid numbers 0-n, look at the number of digits in your number: if n has 5 digits for example, every valid 1, 2, 3, and 4 digit number is in your result set. So for say a 4 digit number, you compute all the possible combinations of digits in that 4 digit number: 1234, 1235, 1236...5678, 5789, and 6789. Then count the number of permutations (1234 can also be 1243, 1324, 1342...etc), and multiply (# of permutations) x (# of distinct sequences you derived in the previous step). Then you have your answer for all 4 digit numbers. Do the same for each other set, and come up with something more specific for your last set; if high is 5500, you need valid numbers between 5000-5100. You can apply a similar algorithm, but instead of using all digits 0-9, you instead use 9 distinct digits, omitting the '5'. Note that all numbers can have a 0 in them as well, but not at the beginning, so the algorithm would need to account for that as well.
Simply convert your number to a string and then run over it while checking if the given char has already occured in your string. e.g. :
#include <string>
int main()
{
std::string s = std::to_string(12345);
bool occuredCheck[10] = {0}; //automatically fills with zeros. 10 values for the 10 numbers
bool isValidNumber = true;
for(int i=s.length()-1; i>=0; ++i)
if(occuredCheck[s[i] - '0'] ^ true == 0) isValidNumber = false;
}
The if-line set's the array-entry to zero, when a diggit occured twice, see XOR.
And isValidNumber lets you know if it actually is a valid number for you.
BTW: This example needs C++11 for std::to_string.
Using this algorithm you may detect the first invalid number and then set your range using it.