Code to find X such that the product (A ^ X) * (B ^ X) is maximised - bit-manipulation

Find X such that (A ^ X) * (B ^ X) is maximum
Given A, B, and N (X < 2^N)
Return the maximum product modulus 10^9+7.
Example:
A = 4
B = 6
N = 3
We can choose X = 3 and (A ^ X) = 7 and (B ^ X) = 5.
The product will be 35 which is the maximum.
Here is my code:
int limit = (1<<n) - 1;
int MOD = 1_000_000_007;
int maxProd = 1;
for(int i = 1; i <= limit; i++){
int x1 = (A^i);
int x2 = (B^i);
maxProd = max(maxProd, (x1*x2) % MOD);
}
return maxProd;

for bits >=Nth bit, X will be zero, A^X and B^X are A and B for those bits
find set bits and zero bits shared by A and B from 0 to N-1th bits. for set bits, X will be zero there. for zero bits, X will be 1 there.
for bits that A and B are different, X will be either 0 or 1
from 1,2, we will have the value for A and B, denoted by a and b. a and b are known constants
from 3, we will have a bunch of 2^k, such as 2^3, 2^1,…, say the tot sum of them is tot. tot is a known constant
the question becomes max (a+tot-sth)*(b+sth), where sth is the subset sum of some 2^k from 3, while a,tot,and b are constants
when (a+tot-sth) and (b+sth) are as close as possible, the product will be maxed.
if a==b, we will give the most significant bit of step 3 to either a or b, and the rest to the other one
if a!=b, we will give all bits in step 3 to the smaller one

Related

Modulo product when the divisor is greater than both large factors

In my C++ code I have three uint64_tvariables:
uint64_t a = 7940678747;
uint64_t b = 59182917008;
uint64_t c = 73624982323;
I need to find (a * b) % c. If I directly multiply a and b, it will cause overflow. However, I can't apply the formula (a * b) % c = ((a % c) * (b % c)) % c, because c > a, c > b and, consequently, a % c = a, a % c = b and I will end up multiplying a and b again, which again will result in overflow.
How can I compute (a * b) % c for these values (and such cases in general) of the variables without overflow?
A simple solution is to define x = 2^32 = 4.29... 10^9
and then to represent a and b as:
a = ka * x + a1 with ka, a1 < x
b = kb * x + b1 with kb, b1 < x
Then
a*b = (ka * x + a1) * (kb * x + b1) = ((ka * kb) * x) * x
+ x * (b1 * ka) + x * (a1 * kb) + a1 * b1
All these operations can be performed without the need of a larger type, assuming that all the operations are performed in Z/cZ, i.e. assuming that % c operation is performed after each operation (* or +)
There are more elegant solutions than this, but an easy one would be looking into a library that deals with larger numbers. It will handle numbers that are too large for the largest of normal types for you. Check this one out: https://gmplib.org/
Create a class or struct to deal with numbers in parts.
Example PsuedoCode
// operation enum to know how to construct a large number
enum operation {
case add;
case sub;
case mult;
case divide;
}
class bigNumber {
//the two parts of the number
int partA;
int partB;
bigNumber(int numA, int numB, operation op) {
if(op == operation.mult) {
// place each digit of numA into an integer array
// palce each digit of numB into an integer array
// Iteratively place the first half of digits into the partA member
// Iteratively place the second half of digits into the partB member
} else if //cases for construction from other operations
}
// Create operator functions so you can perform arithmetic with this class
}
uint64_t a = 7940678747;
uint64_t b = 59182917008;
uint64_t c = 73624982323;
bigNumber bigNum = bigNumber(a, b, .mult);
uint64_t result = bigNum % c;
print(result);
Keep in mind that you may want to make result of type bigNumber if the value of c is very small. Basically this was just sort of an outline, make sure if you use a type that it won't overflow.

Range Update - Range Query using Fenwick Tree

http://ayazdzulfikar.blogspot.in/2014/12/penggunaan-fenwick-tree-bit.html?showComment=1434865697025#c5391178275473818224
For example being told that the value of the function or f (i) of the index-i is an i ^ k, for k> = 0 and always stay on this matter. Given query like the following:
Add value array [i], for all a <= i <= b as v Determine the total
array [i] f (i), for each a <= i <= b (remember the previous function
values ​​clarification)
To work on this matter, can be formed into Query (x) = m * g (x) - c,
where g (x) is f (1) + f (2) + ... + f (x).
To accomplish this, we
need to know the values ​​of m and c. For that, we need 2 separate
BIT. Observations below for each update in the form of ab v. To
calculate the value of m, virtually identical to the Range Update -
Point Query. We can get the following observations for each value of
i, which may be:
i <a, m = 0
a <= i <= b, m = v
b <i, m = 0
By using the following observation, it is clear that the Range Update - Point Query can be used on any of the BIT. To calculate the value of c, we need to observe the possibility for each value of i, which may be:
i <a, then c = 0
a <= i <= b, then c = v * g (a - 1)
b <i, c = v * (g (b) - g (a - 1))
Again, we need Range Update - Point Query, but in a different BIT.
Oiya, for a little help, I wrote the value of g (x) for k <= 3 yes: p:
k = 0 -> x
k = 1 -> x * (x + 1) / 2
k = 2 -> x * (x + 1) * (2x + 1) / 6
k = 3 -> (x * (x + 1) / 2) ^ 2
Now, example problem SPOJ - Horrible Queries . This problem is
similar issues that have described, with k = 0. Note also that
sometimes there is a matter that is quite extreme, where the function
is not for one type of k, but it could be some that polynomial shape!
Eg LA - Alien Abduction Again . To work on this problem, the solution
is, for each rank we make its BIT counter m respectively. BIT combined
to clear the counters c it was fine.
How can we used this concept if:
Given an array of integers A1,A2,…AN.
Given x,y: Add 1×2 to Ax, add 2×3 to Ax+1, add 3×4 to Ax+2, add 4×5 to
Ax+3, and so on until Ay.
Then return Sum of the range [Ax,Ay].

Need clarification about this loop performing multiplication

int x, y; // x is a non-negative integer
p = 0;
while (x > 0)
{
if ( x % 2 == 1 )
p = p + y;
y = y*2;
x = x/2;
}
// p == a*b here
I understand that this loop finds the product of 'a' and 'b' using the algebra:
a * b = (1/2)a * 2b
but I don't understand the code:
if ( x % 2 == 1 )
p = p + y;
I was hoping someone could explain why 'p' is assigned 'p + y' on odd values of x.
while (x > 0) {
if (x % 2 == 1)
p = p + y;
y = y*2;
x = x/2;
}
imagine x = 4, y = 5
iterations:
x is even, y = 10, x = 2 (i.e. x can be divided, y should be doubled)
x is even, y = 20, x = 1
x is odd, p = 20, y = 40, x = 0 (i.e. x can not be divided anymore, y should be added to p)
x > 0 is false, loop ends
p = 4 * y
now imagine x is odd at the beginning, let's say x = 5, y = 2:
x is odd, p = 2, y = 4, x = 2
(5/2 = 2.5, new value of x will be rounded down, y should be added BEFORE it is doubled)
x is even, y = 8, x = 1
x is odd, p = 10, y = 16, x = 0
p = y + 4*y
that first y is the reason, adding it to the result before it is doubled (1 * y) is in this case equivalent to 0.5 * (2 * y)
Because these are integers, a / 2 will be an integer. If a is odd, that integer has been rounded down, and you’re missing one-half b in the next iteration of the loop, i.e. one whole b in the current iteration of the loop (since b [y] is doubled each time).
If x is odd, x = x/2 will set x to 0.5 less than x/2 (because integer division rounds it down). p needs to be adjusted to allow for that.
Think of multiplication as repeated addition, x*y is adding y together x times. It is also the same as adding 2*y together x/2 times. Conceptually it is somewhat unclear what it means if x is odd. For example, if x=5 and y=3, what does it mean to add 2.5 times? The code notices when x is odd, adds y in, then does the y=y*2 and x=x/2. When x is odd, this throws away the .5 part. So in this example, you add y one time, then x becomes 2 (not 2.5) because integer division throws away the fraction.
At the end of each loop, you will see that the product of the original x and y is equal to p + x*y for the current values of p, x, and y. The loop iterates until x is 0, and the result is entirely in p.
It also helps to see what is going on if you make a table and update it each time through the loop. These are the values at the start of each iteration:
x | y | p
----------
5 | 3 | 0
2 | 6 | 3
1 | 12 | 3
0 | 24 | 15
This works by observing that (for example) y * 10 = y * 8 + y * 2.
It's pretty much like doing multiplication on paper in school. For example, to multiply 14 x 21, we multiply one digit at a time (and shift left a place where needed) so we add 1x14 + 2 x 14 (shifted left one digit).
14
x 21
----
14
280
Here, we're doing pretty much the same thing, but working in binary instead of decimal. The right shifting has nothing to do with the numbers being odd, and everything to do with simply finding which bits in the number are set.
As we shift one operand right to find whether a bit is set, we also shift the other operand left, just like we add zeros to shift numbers left when doing arithmetic on paper in decimal.
So, viewing things in binary, we end up with something like:
101101
x 11010
--------
1011010
+ 101101000
+ 1011010000
If we wanted to, instead of shifting the operand right, we could just shift the mask left so instead of repeatedly anding with 1, we'd and with 1, then with 2, then with 4, and so on (in fact, it would probably make a lot more sense that way). For better or worse, however, in assembly language (where this sort of thing is normally done) it's usually a little easier to shift the operand and use a constant for the mask than load the mask in a register and shift it when needed.
You should rewrite x as 2*b+1 (assuming x is odd). Then
x*y = (2*b+1)*y = (2*b)*y + y = b*(2*y) + y = (x/2)*(2*y) + y
where (x/2) is meant to be the integer division. With the operation rewritten this way, you see the x/2, the 2y and the +y appear.

Properties of the modulo operation

I have the compute the sum S = (a*x + b*y + c) % N. Yes it looks like a quadratic equation but it is not because the x and y have some properties and have to be calculated using some recurrence relations. Because the sum exceeds even the limits of unsigned long long I want to know how could I compute that sum using the properties of the modulo operation, properties that allow the writing of the sum something like that(I say something because I do not remember exactly how are those properties): (a*x)%N + (b*y)%N + c%N, thus avoiding exceeding the limits of unsigned long long.
Thanks in advance for your concern! :)
a % N = x means that for some integers 0 <= x < N and m: m * N + x = a.
You can simply deduce then that if a % N = x and b % N = y then
(a + b) % N =
= (m * N + x + l * N + y) % N =
= ((m + l) * N + x + y) % N =
= (x + y) % N =
= (a % N + b % N) % N.
We know that 0 < x + y < 2N, that is why you need to keep remainder calculation. This shows that it is okay to split the summation and calculate the remainders separately and then add them, but don't forget to get the remainder for the sum.
For multiplication:
(a * b) % N =
= ((m * N + x) * (l * N + y)) % N =
= ((m * l + x * l + m * y) * N + x * y) % N =
= (x * y) % N =
= ((a % N) * (b % N)) % N.
Thus you can also do the same with products.
These properties can be simply derived in a more general setting using some abstract algebra (the remainders form a factor ring Z/nZ).
You can take the idea even further, if needed:
S = ( (a%N)*(x%N)+(b%N)*(y%N)+c%N )%N
You can apply the modulus to each term of the sum as you've suggested; but even so after summing them you must apply the modulus again to get your final result.
How about this:
int x = (7 + 7 + 7) % 10;
int y = (7 % 10 + 7 % 10 + 7 % 10) % 10;
You remember right. The equation you gave, where you %N every of the summands is correct. And that would be exactly what I use. You should also %N for every partial sum (and the total) again, as the addition results can be still greater than N. BUT be careful this works only if your size limit is at least twice as big as your N. If this is not the case, it can get really nasty.
Btw for the following %N operations of the partial sums, you dont have to perform a complete division, a check > N and if bigger just subtraction of N is enough.
Not only can you reduce all variable mod n before starting the calculation, you can write your own mod-mul to compute a*x mod n by using a shift-and-add method and reduce the result mod n at each step. That way your intermediate calculations will only require one more bit than n. Once these products are computed, you can add them pairwise and reduce mod n after each addition which will also not require more than 1 bit beyond the range of n.
There is a python implementation of modular multiplication in my answer to this question. Conversion to C should be trivial.

Find the sum of all numbers between 1 and N divisible by either x or y

Say we have 3 numbers N, x and y which are always >=1.
N will be greater than x and y and x will be greater than y.
Now we need to find the sum of all number between 1 and N that are divisible by either x or y.
I came up with this:
sum = 0;
for(i=1;i<=N;i++)
{
if(i%x || i%y)
sum += i;
}
Is there a way better way of finding the sum avoiding the for loop?
I've been pounding my head for many days now but have not got anything better.
If the value of N has a upper limit we can use a lookup method to speedup the process.
Thanks everyone.
I wanted a C/C++ based solution. Is there a built-in function to do this? Or do I have to code the algorithm?
Yes. You can void the for loop altogether and find the sum in constant time.
According to the Inclusion–exclusion principle summing up the multiples of x and multiples of y and subtracting the common multiple(s) that got added twice should give us the required sum.
Required Sum = sum of ( multiples of x that are <= N ) +
sum of ( multiples of y that are <= N ) -
sum of ( multiples of (x*y) that are <= N )
Example:
N = 15
x = 3
y = 4
Required sum = ( 3 + 6 + 9 + 12 + 15) + // multiples of 3
( 4 + 8 + 12 ) - // multiples of 4
( 12 ) // multiples of 12
As seen above we had to subtract 12 as it got added twice because it is a common multiple.
How is the entire algorithm O(1)?
Let sum(x, N) be sum of multiples of x which are less than or equal to N.
sum(x,N) = x + 2x + ... + floor(N/x) * x
= x * ( 1 + 2 + ... + floor(N/x) )
= x * ( 1 + 2 + ... + k) // Where k = floor(N/x)
= x * k * (k+1) / 2 // Sum of first k natural num = k*(k+1)/2
Now k = floor(N/x) can be computed in constant time.
Once k is known sum(x,N) can be computed in constant time.
So the required sum can also be computed in constant time.
EDIT:
The above discussion holds true only when x and y are co-primes. If not we need to use LCM(x,y) in place of x*y. There are many ways to find LCM one of which is to divide product by GCD. Now GCD cannot be computed in constant time but its time complexity can be made significantly lesser than linear time.
If a number is divisible by X, it has to be a multiple of x.
If a number is divisible by Y, it has to be a multiple of y.
I believe, if you do a for loop for all multiples of x and y, and avoid any duplicates, you should get the same answer.
Out of my head, something of the type:
sum = 0
for( i=x; i<=n; i+=x)
sum += i;
for( i=y; i<=n; i+=y)
if( y % x != 0 )
sum += i;