Determine which fraction is better - algorithm

Given two fractions, determine which fraction has more potential to give a max value.
For example we have fractions 1/2 and 2/4, for this example I picked 2 random fractions: 3/4, 5/3 (I don't know what this fractions will be, I just know that n 1..100, d 1..100)
Sum all n and d then divide
1. Fraction 1/2, sum with 3/4, 5/3
(1+3+5) / (2+4+3) = 9/9 = 1
2. Fraction 2/4 sum with 3/4, 5/3
(2+3+5) / (4+4+3) = 10/11 = 0.90
For the above example the output would be 1/2. But will this be true when instead of 3/4, 5/3 we have all the fractions [1..100]/[1..100]?

Let's fix the sum of the numerators of the two random fractions (let's denote as num) and the sum of their denominators (denom). Then we know we the result of the comparison. We just need to find the number of ways to represent the num and the denom as the sum of two fractions. It's exactly min(100, x - 1) - max(x - 100, 1) + 1.
So we just need to iterate over all possible numerator and denominator sums. There're only 199 * 199 different options.
However, 100^4 is a pretty small number, so you can just iterate over all possible numerators and denominators of the two random fractions, too.

Related

Making a very large calculation

I am want to calculate the value X =n!/2^r
where n<10^6 and r<10^6
and it's guarantee that value of X is between O to 10
How to calculate X since i can't simple divide the factorial and power term since they overflow the long integer.
My Approach
Do with the help of Modulus. Let take a prime number greater than 10 let say 101
X= [(Factorial N%101)*inverse Modulo of(2^r)]%101;
Note that inverse modulo can easily be calculate and 2^r%101 can also be calculated.
Problem:
It's not guarantee that X is always be integer it can be float also.
My method works fine when X is integer ? How to deal when X is a floating point number
If approximate results are OK and you have access to a math library with base-2 exponential (exp2 in C), natural log gamma (lgamma in C), and natural log (log in C), then you can do
exp2(lgamma(n+1)/log(2) - r).
Find the power that 2 appears at in n!. This is:
P = n / 2 + n / 2^2 + n / 2^3 + ...
Using integer division until you reach a 0 result.
If P >= r, then you have an integer result. You can find this result by computing the factorial such that you ignore r powers of 2. Something like:
factorial = 1
for i = 2 to n:
factor = i
while factor % 2 == 0 and r != 0:
factor /= 2
r -= 1
factorial *= factor
If P < r, set r = P, apply the same algorithm and divide the result by 2^(initial_r - P) in the end.
Except for a very few cases (with small n and r) X will not be an integer -- for if n >= 11 then 11 divides n! but doesn't divide any power of two, so if X were integral it would have to be at least 11.
One method would be: initialise X to one; then loop: if X > 10 divide by 2 till its not; if X < 10 multiply by the next factors till its not; until you run out of factors and powers of 2.
An approach that would be tunable for precision/performance would be the following:
Store the factorial in an integer with a fixed number of bits. We can drop the last few digits if the number gets too large, since they won't affect the overall result altogether that much. By scaling this integer larger/smaller the algorithm gets tunable for either performance or precision.
Whenever the integer would overflow due to multiplication, shift it to the right by a few places and subtract that value from r. In the end there should be a small number left as r and an integer v with the most significant bits of the factorial. This v can now be interpreted as a fixed-point number with r fractional digits.
Depending upon the required precision this approach might even work with long, though I haven't had the time to test this approach yet apart from a bit experimenting with a calculator.

Find prime factors such that difference is smallest as possible

Suppose n, a, b are positive integers where n is not a prime number, such that n=ab with a≥b and (a−b) is small as possible. What would be the best algorithm to find the values of a and b if n is given?
I read a solution where they try to represent n as the difference between two squares via searching for a square S bigger than n such that S - n = (another square). Why would that be better than simply finding the prime factors of n and searching for the combination where a,b are factors of n and a - b is minimized?
Firstly....to answer why your approach
simply finding the prime factors of n and searching for the combination where a,b are factors of n and a - b is minimized
is not optimal:
Suppose your number is n = 2^7 * 3^4 * 5^2 * 7 * 11 * 13 (=259459200), well within range of int. From the combinatorics theory, this number has exactly (8 * 5 * 3 * 2 * 2 * 2 = 960) factors. So, firstly you find all of these 960 factors, then find all pairs (a,b) such that a * b = n, which in this case will be (6C1 + 9C2 + 11C3 + 13C4 + 14C5 + 15C6 + 16C7 + 16C8) ways. (if I'm not wrong, my combinatorics is a bit weak). This is of the order 1e5 if implemented optimally. Also, implementation of this approach is hard.
Now, why the difference of squares approach
represent S - n = Q, such that S and Q are perfect squares
is good:
This is because if you can represent S - n = Q, this implies, n = S - Q
=> n = s^2 - q^2
=> n = (s+q)(s-q)
=> Your reqd ans = 2 * q
Now, even if you iterate for all squares, you will either find your answer or terminate when difference of 2 consecutive squares is greater than n
But I don't think this will be doable for all n (eg. if n=6, there is no solution for (S,Q).)
Another approach:
Iterate from floor(sqrt(n)) to 1. The first number (say, x), such that x|n will be one of the numbers in the required pair (a,b). Other will be, obvs, y = x/n. So, your answer will be y - x.
This is O(sqrt(n)) time complex algorithm.
A general method could be this:
Find the prime factorization of your number: n = Π pi ai. Except for the worst cases where n is prime or semiprime, this will be substantially faster than O(n1/2) time of the iteration down from the square root, which won't divide the found factors out of the number.
Recall that the simplest, trial division, prime factorization is done by repeatedly trying to divide the number by increasing odd numbers (or by primes) below the number's square root, dividing out of the number each factor -- thus prime by construction -- as it is found (n := n/f).
Then, lazily enumerate the factors of n in order from its prime factorization. Stop after producing half of them. Having thus found n's (not necessarily prime) factor that is closest to its square root, find the second factor by simple division.
In case this must repeatedly run many times, it will greatly pay out to precalculate the needed primes below the n's square root, to use in the factorizations.

Largest divisor such that two numbers divided by it round to the same value?

I've got an algorithm that can be interpreted as dividing up the number line into an equal number of chunks. For simplicity, I'll stick with [0,1), it will be divided up like so:
0|----|----|----|----|1
What I need to do is take a range of numbers [j,k) and find the largest number of chunks, N, up to some maximum M, that will divide up the number line so that [j,k) still all fall into the same "bin". This is trickier than it sounds, as the range can straddle a bin like so:
j|-|k
0|----|----|----|----|1
So that you may have to get to quite a low number before the range is entirely contained. What's more, as the number of bins goes up, the range may move in and out of a single bin, so that there's local minima.
The obvious answer is to start with M bins, and decrease the number until the range falls into a single bin. However, I'd like to know if there's a faster way than enumerating all possible divisions, as my maximum number can be reasonable large (80 million or so).
Is there a better algorithm for this?
Here I would like to give another heuristic, which is different from btilly's.
The task is to find integers m and n such that m / n <= j < k <= (m + 1) / n, with n as big as possible (but still under M).
Intuitively, it is preferable that the fraction m / n is close to j. This leads to the idea of using continued fractions.
The algorithm that I propose is quite simple:
calculate all the continued fractions of j using minus signs (so that the fractions are always approching j from above), until the denominator exceeds M;
for each such fraction m / n, find the biggest integer i >= 0 such that k <= (m * i + 1) / (n * i) and n * i <= M, and replace the fraction m / n with (m * i) / (n * i);
among all the fractions in 2, find the one with biggest denominator.
The algorithm is not symmetric in j and k. Hence there is a similar k-version, which in general should not give the same answer, so that you can choose the bigger one from the two results.
Example: Here I will take btilly's example: j = 0.6 and k = 0.65, but I will take M = 10.
I will first go through the j-procedure. To calculate the continued fraction expansion of j, we compute:
0.6
= 0 + 0.6
= 0 + 1 / (2 - 0.3333)
= 0 + 1 / (2 - 1 / (3 - 0))
Since 0.6 is a rational number, the expansion terminates in fintely many steps. The corresponding fractions are:
0 = 0 / 1
0 + 1 / 2 = 1 / 2
0 + 1 / (2 - 1 / 3) = 3 / 5
Computing the corresponding i values in step 2, we replaces the three factions with:
0 / 1 = 0 / 1
1 / 2 = 3 / 6
3 / 5 = 6 / 10
The biggest denominator is given by 6 / 10.
Continue with the example above, the corresponding k-procedure goes as follows:
0.65
= 1 - 0.35
= 1 - 1 / (3 - 0.1429)
= 1 - 1 / (3 - 1 / (7 - 0))
Hence the corresponding fractions:
1 = 1 / 1
1 - 1 / 3 = 2 / 3
1 - 1 / (3 - 1 / 7) = 13 / 20
Passing step 2, we get:
1 / 1 = 2 / 2
2 / 3 = 6 / 9
13 / 20 = 0 / 0 (this is because 20 is already bigger than M = 10)
The biggest denominator is given by 6 / 9.
EDIT: experimental results.
To my surprise, the algorithm works better than I thought.
I did the following experiment, with the bound M ignored (equivalently, one can take M big enough).
In every round, I generate a pair (j, k) of uniformly distributed random numbers in the inteval [0, 1) with j < k. If the difference k - j is smaller than 1e-4, I discard this pair, making this round ineffective. Otherwise I calculate the true result trueN using naive algorithm, and calculate the heuristic result heurN using my algorithm, and add them to statistic data. This goes for 1e6 rounds.
Here is the result:
effective round = 999789
sum of trueN = 14013312
sum of heurN = 13907575
correct percentage = 99.2262 %
average quotient = 0.999415
The correct percentage is the percentage of effective rounds such that trueN is equal to heurN, and the average quotient is the average of the quotient heurN / trueN for all effective rounds.
Thus the method gives the correct answer in 99%+ cases.
I also did experiments with smaller M values, and the results are similar.
The best case for the bin size must be larger than k-j.
Consider the number line segments [0..j]and [k..1). If we can divide both of the partial segments into parts using the same bin size, we should be able to solve the problem.
So if we consider gcd((j-0)/(k-j), (1-k)/(k-j)), (where we use the greatest-integer-function after the division), we should be able to get a good estimate, or the best value. There are corner cases: if (k-j) > j or (k-j) > (1-k), the best value is 1 itself.
So a very good estimate should be min(1, (k-j) * gcd((j-0)/(k-j), (1-k)/(k-j)))
Let's turn this around a bit.
You'd like to find m, n as large as you can (though n < M) with m/n close to but less than j and k <= (m+1)/n.
All promising candidates will be on the https://en.wikipedia.org/wiki/Stern%E2%80%93Brocot_tree. Indeed you'll get a reasonably good answer just walking the Stern-Brocot tree to find the last "large rational" fitting your limit just below j whose top is at k or above.
There is a complication. Usually the tree converges quickly. But sometimes the Stern-Brocot tree has long sequences with very small gaps. For example the sequence to get to 0.49999999 will include 1/3, 2/5, 3/7, 4/9, ... We always fall into those sequences when a/b < c/d, then we take the median (a+c)/(b+d) and then we walk towards one side, so (a+i*c)/(b+i*d). If you're clever, then rather than walking the whole sequence you can just do a binary search for the right power of i to use.
The trick to that cleverness is to view your traversal as:
Start with 2 "equal" fractions.
Take their median. If that exceeds M then I'm done. Else figure out which direction I am going from that.
Try powers of 2 in (a+i*c)/(b+i*d) until I know what range i is in for my range and M conditions.
Do binary search to find the last i that I can use.
(a+i*c)/(b+i*d) and (a+i*c+c)/(b+i*d+d) are my two new equal fractions. Go back to the first step.
The initial equal fractions are, of course, 0/1 and 1/1.
This will always find a decent answer in O(log(M)) operations. Unfortunately this reasonably good answer is NOT always correct. Consider the case where M = 3, j=0.6 and k=0.65. In this case the heuristic would stop at 1/2 while the actual best answer is 1/3.
Another way that it can fail is that it only finds reduced answers. In the above example if M was 4 then it still thinks that the best answer is 1/2 when it is actually 1/4. It is easy to handle this by testing whether a multiple of your final answer will work. (That step will improve your answer a fixed, but reasonably large, fraction of the time.)

Fast algorithm to calculate large n! mod 2³²

I want to calculate the exact value of N! mod 232. N can be up to 231
Any language is fine but I would appreciate detailed explanation of algorithm.
Time limit is < 1 sec
In python:
if n > 33:
return 0
else
return reduce(lambda x, y: x*y, range(1, n+1)) % 2**32
Justification:
We know that 34! is divisible by 232 because in the sequence:
1 * 2 * 3 * 4 * ... * 34
there are:
17 multiples of 2
8 multiples of 4
4 multiples of 8
2 multiples of 16
1 multiple of 32
--
32 multiplications by 2
It's a factor of every larger factorial, so all the larger ones are 0 mod 232
For small values of N, if you don't have bignum arithmetic available, you can do the individual multiplications mod 232, and/or you can prefactor the power of 2 in the factorial, which is easy to compute (see above).
Calculate the factorial normally (multiply the numbers 1,2,3,...), performing the modulo after each multiplication. This will give you the result for small values of N.
For larger values of N, do the same. Pretty soon, your intermediate result will be 0, and then you can stop the loop immediately and return 0. The point at which you stop will be relatively fast: For N == 64 the result will already be 0 because the product of 1..64 contains 32 even numbers and is therefore divisible by 2^32. The actual minimal value of N where you get 0 will be less than 64.
In general, you can implement algorithms modulo small powers of two without bignums or modular reduction using the integer types (int, long) available in most programming languages. For modulo 232 you would use a 32-bit int. "Integer overflow" takes care of the modular arithmetic.
In this case, since there are only 34 distinct results, a lookup table may be faster than computing the factorial, assuming the factorials are used often enough that the table gets loaded into the CPU cache. The execution time will be measured in microseconds.
When multiplying 2 numbers of arbitrary length, the lower bits are always exact because it doesn't depend on high order bits. Basically a×b mod m = [(a mod m)×(b mod m)] mod m so to do N! mod m just do
1×2×...×N mod m = (...(((1×2 mod m)×3 mod m)×4 mod m)...)×N mod m
Modulo 2n is a special case because getting the modulus is rather easy with an AND operation. Modulo 232 is even more special because all unsigned operations in C and most C-like languages are reduced modulo 232 for a 32-bit unsigned type
As a result you can just multiply the numbers in a twice-as-wide type then after that AND with 232 - 1 to get the modulus
uint64_t p = 1;
for (uint32_t i = 1; i <= n; i++)
p = p*i & 0xFFFFFFFFU;
return p;
Calculating a modulo is a very fast operation, especially the modulo of a power of 2. A multiplication is very costly in comparison.
The fastest algorithm would factorize the factors of the factorial in prime numbers (which is very fast since the numbers are smaller than 33). And get the result by multiplying all of them together, by taking the modulo in between each multiplication, and starting with the big numbers.
E.g.: to calculate 10! mod 232: use de Polignac's formula, to get the prime factors of 10!
which gives you :
10! = 7 * 5 * 5 * 3 * 3 * 3 * 3 * 2 ...
this would be faster than the basic algorithm, because calculating
(29! mod 232) X 30
is much harder than multiplying by 5, 3 and 2, and taking the modulo in between each time.

Calculating sum of geometric series (mod m)

I have a series
S = i^(m) + i^(2m) + ............... + i^(km) (mod m)
0 <= i < m, k may be very large (up to 100,000,000), m <= 300000
I want to find the sum. I cannot apply the Geometric Progression (GP) formula because then result will have denominator and then I will have to find modular inverse which may not exist (if the denominator and m are not coprime).
So I made an alternate algorithm making an assumption that these powers will make a cycle of length much smaller than k (because it is a modular equation and so I would obtain something like 2,7,9,1,2,7,9,1....) and that cycle will repeat in the above series. So instead of iterating from 0 to k, I would just find the sum of numbers in a cycle and then calculate the number of cycles in the above series and multiply them. So I first found i^m (mod m) and then multiplied this number again and again taking modulo at each step until I reached the first element again.
But when I actually coded the algorithm, for some values of i, I got cycles which were of very large size. And hence took a large amount of time before terminating and hence my assumption is incorrect.
So is there any other pattern we can find out? (Basically I don't want to iterate over k.)
So please give me an idea of an efficient algorithm to find the sum.
This is the algorithm for a similar problem I encountered
You probably know that one can calculate the power of a number in logarithmic time. You can also do so for calculating the sum of the geometric series. Since it holds that
1 + a + a^2 + ... + a^(2*n+1) = (1 + a) * (1 + (a^2) + (a^2)^2 + ... + (a^2)^n),
you can recursively calculate the geometric series on the right hand to get the result.
This way you do not need division, so you can take the remainder of the sum (and of intermediate results) modulo any number you want.
As you've noted, doing the calculation for an arbitrary modulus m is difficult because many values might not have a multiplicative inverse mod m. However, if you can solve it for a carefully selected set of alternate moduli, you can combine them to obtain a solution mod m.
Factor m into p_1, p_2, p_3 ... p_n such that each p_i is a power of a distinct prime
Since each p is a distinct prime power, they are pairwise coprime. If we can calculate the sum of the series with respect to each modulus p_i, we can use the Chinese Remainder Theorem to reassemble them into a solution mod m.
For each prime power modulus, there are two trivial special cases:
If i^m is congruent to 0 mod p_i, the sum is trivially 0.
If i^m is congruent to 1 mod p_i, then the sum is congruent to k mod p_i.
For other values, one can apply the usual formula for the sum of a geometric sequence:
S = sum(j=0 to k, (i^m)^j) = ((i^m)^(k+1) - 1) / (i^m - 1)
TODO: Prove that (i^m - 1) is coprime to p_i or find an alternate solution for when they have a nontrivial GCD. Hopefully the fact that p_i is a prime power and also a divisor of m will be of some use... If p_i is a divisor of i. the condition holds. If p_i is prime (as opposed to a prime power), then either the special case i^m = 1 applies, or (i^m - 1) has a multiplicative inverse.
If the geometric sum formula isn't usable for some p_i, you could rearrange the calculation so you only need to iterate from 1 to p_i instead of 1 to k, taking advantage of the fact that the terms repeat with a period no longer than p_i.
(Since your series doesn't contain a j=0 term, the value you want is actually S-1.)
This yields a set of congruences mod p_i, which satisfy the requirements of the CRT.
The procedure for combining them into a solution mod m is described in the above link, so I won't repeat it here.
This can be done via the method of repeated squaring, which is O(log(k)) time, or O(log(k)log(m)) time, if you consider m a variable.
In general, a[n]=1+b+b^2+... b^(n-1) mod m can be computed by noting that:
a[j+k]==b^{j}a[k]+a[j]
a[2n]==(b^n+1)a[n]
The second just being the corollary for the first.
In your case, b=i^m can be computed in O(log m) time.
The following Python code implements this:
def geometric(n,b,m):
T=1
e=b%m
total = 0
while n>0:
if n&1==1:
total = (e*total + T)%m
T = ((e+1)*T)%m
e = (e*e)%m
n = n/2
//print '{} {} {}'.format(total,T,e)
return total
This bit of magic has a mathematical reason - the operation on pairs defined as
(a,r)#(b,s)=(ab,as+r)
is associative, and the rule 1 basically means that:
(b,1)#(b,1)#... n times ... #(b,1)=(b^n,1+b+b^2+...+b^(n-1))
Repeated squaring always works when operations are associative. In this case, the # operator is O(log(m)) time, so repeated squaring takes O(log(n)log(m)).
One way to look at this is that the matrix exponentiation:
[[b,1],[0,1]]^n == [[b^n,1+b+...+b^(n-1))],[0,1]]
You can use a similar method to compute (a^n-b^n)/(a-b) modulo m because matrix exponentiation gives:
[[b,1],[0,a]]^n == [[b^n,a^(n-1)+a^(n-2)b+...+ab^(n-2)+b^(n-1)],[0,a^n]]
Based on the approach of #braindoper a complete algorithm which calculates
1 + a + a^2 + ... +a^n mod m
looks like this in Mathematica:
geometricSeriesMod[a_, n_, m_] :=
Module[ {q = a, exp = n, factor = 1, sum = 0, temp},
While[And[exp > 0, q != 0],
If[EvenQ[exp],
temp = Mod[factor*PowerMod[q, exp, m], m];
sum = Mod[sum + temp, m];
exp--];
factor = Mod[Mod[1 + q, m]*factor, m];
q = Mod[q*q, m];
exp = Floor[ exp /2];
];
Return [Mod[sum + factor, m]]
]
Parameters:
a is the "ratio" of the series. It can be any integer (including zero and negative values).
n is the highest exponent of the series. Allowed are integers >= 0.
mis the integer modulus != 0
Note: The algorithm performs a Mod operation after every arithmetic operation. This is essential, if you transcribe this algorithm to a language with a limited word length for integers.

Resources