Related
Time limit per test: 2 seconds
Memory limit per test: 512 megabytes
You are given two fractions a/b < c/d and a positive number N.
Consider all irreducible fractions e/f such that 0 < e, f ≤ N and
a/b < e/f < c/d. Let s be a sequence of these fractions
sorted in ascending order of denominators and then numerators (fraction
e1/f1 precedes e2/f2 if either f1 < f2 or f1 = f2 and e1 < e2). You should print first n terms of the sequence s or the
whole sequence s if it consists of fewer than n terms.
Input
The first line of each test contains 6 integers a, b, c, d, N, n (0 ≤ a ≤ 10^18, 1 ≤ b, c, d, N ≤ 10^18, 1 ≤ n ≤ 200 000, a/b < c/d).
Output
First, print how many terms of sequence s you will output. And then output these terms in the right order.
Examples
Input:
0 1 1 1 5 10
Output:
9
1 2
1 3
2 3
1 4
3 4
1 5
2 5
3 5
4 5
Input:
55 34 68 42 90 1
Output:
1
89 55
Input:
49 33 45 30 50 239
Output:
0
So far, I've only managed to write a solution that iterates over all the denominators from 1 to N, and for each denominator iterates over all the numerators from a*f/b to c*f/d, adding all found irreducible fractions to the answer.
Here is my code:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
long long a, b, c, d, N, n;
vector<pair<long long, long long>> result;
long long gcd(long long a, long long b) {
while (b) {
a %= b;
swap(a, b);
}
return a;
}
void computeResult() {
for (long long f = 1; f <= N; f++) {
long long eMax = c*f / d;
if (c*f % d != 0) eMax++;
eMax = min(eMax, N);
for (long long e = a*f / b + 1; e < eMax; e++) {
if (gcd(e, f) == 1) {
result.push_back(make_pair(e, f));
if (result.size() == n)
return;
}
}
}
}
int main() {
cin >> a >> b >> c >> d >> N >> n;
computeResult();
cout << result.size() << endl;
for (pair<long long, long long> fraction : result)
cout << fraction.first << " " << fraction.second << endl;
}
Unfortunately, this solution is too slow. I wonder how to solve this problem more efficiently.
This is a very interesting question and I really enjoyed thinking about it, and I don't know why it received so many downvotes. Anyways, the below is my rough sketch of the solution. I will update my answer later if I add some refinement to it.
As suggested by #user3357359 answer, we need a more effective way to generate coprimes. A common technique (that is used in diophantine equation solvers) is Farey Sequence.
Definition: a Farey Sequence of order n between a/b and c/d is the ascending (by value) sequence of irreducible fractions p/q such that a/b <= p/q <= c/d, where q < n.
Properties of Farey Sequence is presented in this paper.
So, we have several questions at hand:
How to effectively generate Farey Sequence of order n?
Knowing the first element a0/b0 = a/b and the second element a1/b1, one can generate a2/b2 using the following algorithm (with complexity O(1)):
k = int((n + b0) / b1)
a2 = k * a1 - a0
b2 = k * b1 - b0
How to get the second element of Farey Sequence of order n?
We know that the denominator is somewhere in the range 1..n. We also know that a/b and c/d are neighbors in Farey Sequence if and only if b*c - a*d = 1. So by itering the value of d through 1..n we can find the smallest fraction, which will the the next one in the sequence. Complexity O(n).
How do we decide which order of Farey Sequence we should generate?
Blindly generating of order N, when N is in magnitude of 10^18 is stupid. Moreover, you won't have enough memory for that. We only need to generate a Farey Sequence of some order k, such that the length of it is larger than n which is bounded by 200000. This is the hardest part of this algorithm, and right now the tools in number theory only allows us to estimate: |F_k| = 3*k^2 / pi^2. So we have:
k = ceil(sqrt(n * pi^2)) + C
In page 11 of this paper you can also find the approximation error of this formula, so that you accomodate more room for error, thus the C. Note that, for each a/b and c/d, the length of F_k would be different.
To sum up, the pseudocode for the algorithm is:
1. Estimate the order k of the Farey Sequence to generate, such that |F_k| >= n
2. Calculate the second element of F_k. O(k), where k << n and 1 < n < 200000
3. Generate the whole Farey Sequence. O(n), where 1 < n < 200000
4. Sort by the requirements. O(n log n), where 1 < n < 200000
In the worst case scenario when your estimation in step 1 gave less elements than n, you'll need to generate again, using a bit higher order k'. Which will only increase the execution time of your algorithm by a constant. So, the overall complexity is O(n log n) in average, where n < 200000.
Remarks: the bottleneck of this algorithm is estimation of order k. This might be avoided completely by using not Farey Sequence, but the Stern-Brocot Tree. The tree generates exactly in the order that you need, but I doubt that in an arbitrary setting with a/b != 0/1 and c/d != 1/1 it will iterate through all the fractions in a good order.
You should iterate over all denominators from 1 to N, but you don't need to iterate over all numerators in the given range.
For any irreducible fraction numerator/denominator, numerator and denominator are coprimes. So what you need is to efficiently generate all coprimes of denominator for which co-prime/denominator lie in the given range.
For example, for denominator = 8, coprimes are 1,3,5,7. The irreducible fractions in the range [0,1] are 1/8, 3/8, 5/8, 7/8. You can expand this range of irreducible fractions by adding a integer to them: 1+1/8, 1+3/8, 1+5/8, 1+7/8 => 9/8, 11/8, 13/8, 15/8 are the irreducible fractions with 8 as denominator in the range [0+1,1+1] = > [1,2]
Pseudo-code for generating all coprimes of x such that a/b < coprime/x < c/d :
prime_factors_of_x = get_prime_factors(x)
is_coprime = boolean array of size x
set every element of is_coprime to True
// next, set to False all elements indexed by multiples of a prime factor of x
for every factor in prime_factors_of_x:
// next loop can be a vectorial operation in some languages
for i in 0..(x/factor):
is_coprime[i*factor] = False
all_coprime_list = [] // empty list
min_coprime = floor(a/b * x)+1
max_coprime = floor(c/d * x)-1
for i in min_coprime..max_coprime:
if is_coprime[i mod x]:
all_coprimes_list.append(i)
This is the overall idea.
Apart from the other problem, you will notice that it sort works if N=10^9, but if N=10^18 then your code will have overflow when multiplying by f, and everything will fall apart. You can do long long eMax = (long long)(((long double)c) * f / d);
(and similarly for lower bound) to reduce that problem, but it will slow it down.
(beginner here)
I want to know how to find n-th number of the sequence F[n]=F[n-1]+F[n-2].
Input:
F[0] = a;
F[1] = b;
a,b < 101
N < 1000000001
M < 8; M=10^M;
a and b are starting sequence numbers.
n is the n-th number of the sequence i need to find.
M is modulo, the number gets very large quickly so F[n]=F[n]%10^M, we find the remainder, because only last digits of the n-th number are needed
The recursive approach is too slow:
int fib(int n)
{
if (n <= 1)
return n;
return fib(n-1) + fib(n-2);
}
The dynamic programming solution which takes O(n) time is also too slow:
f[i] = f[i-1] + f[i-2];
While there are solutions on how to find n-th number faster if first numbers of the sequence are 0 and 1 (n-th number can be found in O(log n)) by using this formula:
If n is even then k = n/2:
F(n) = [2*F(k-1) + F(k)]*F(k)
If n is odd then k = (n + 1)/2
F(n) = F(k)*F(k) + F(k-1)*F(k-1)
(link to formula and code implementation with it: https://www.geeksforgeeks.org/program-for-nth-fibonacci-number/)
But this formula does not work if starting numbers are something like 25 and 60. And the recursive approach is too slow.
So I want to know how can I find the n-th number of a sequence faster than O(n). Partial code would be helpful.
Thank you.
This matrix:
A = / 1 1 \
\ 1 0 /
When multiplied by the column vector (fn+1, fn), where fn is the nth number in a Fibonacci sequence, will give you the column vector (fn+2, fn+1), i.e. it will advance you by one step. This works no matter what the initial elements of the sequence were.
For example:
/ 1 1 \ / 8 \ = / 13 \
\ 1 0 / \ 5 / \ 8 /
So the nth fibonacci number is the first element of An-1v, where v is a column vector containing f1 and f0, the first two numbers in your sequence.
Therefore, if you can quickly calculate An-1 modulo some number, this will give you fn. This can be done using Exponentiation by squaring, which works in O(logn). Just make sure to perform the modulo after every multiplication and addition to prevent the numbers from getting too big.
So, I was asked this question in an interview. Given a group of numbers (not necessarily distinct), I have to find the multiplication of GCD's of all possible subsets of the given group of numbers.
My approach which I told the interviewer:
1. Recursively generate all possible subsets of the given set.
2a. For a particular subset of the given set:
2b. Find GCD of that subset using the Euclid's Algorithm.
3. Multiply it in the answer being obtained.
Assume GCD of an empty set to be 1.
However, there will be 2^n subsets and this won't work optimally if the n is large. How can I optimise it?
Assume that each array element is an integer in the range 1..U for some U.
Let f(x) be the number of subsets with GCD(x). The solution to the problem is then the sum of d^f(d) for all distinct factors 1 <= d <= U.
Let g(x) be the number of array elements divisible by x.
We have
f(x) = 2^g(x) - SUM(x | y, f(y))
We can compute g(x) in O(n * sqrt(U)) by enumerating all divisors of every array element. f(x) can be computed in O(U log U) from high to low values, by enumerating every multiple of x in the straightforward manner.
Pre - Requisite :
Fermat's little theorem (there is a generalised theorem too) , simple maths , Modular exponentiation
Explanation : Notations : A[] stands for our input array
Clearly the constraints 1<=N<=10^5 , tell me that either you need a O(N * LOG N ) solution , dont try to think DP as its complexity according to me will be N * max(A[i]) i.e. approx. 10^5 * 10 ^ 6 . Why? because you need the GCD of the subsets to make a transition.
Ok , moving on
We can think of clubbing the subsets with the same GCD so as to make the complexity.
So , lets decrement an iterator i from 10^6 to 1 trying to make the set with GCD i !
Now to make the subset with GCD(i) I can club it with any i*j where j is a non negative Integer. Why ?
GCD(i , i*j ) = i
Now ,
We can build a frequency table for any element as the number is quite reachable!
Now , during the contest what I did was , keep the number of subsets with gcd(i) at f2[i]
hence what we do is sum frequency of all elements from j*i where j varies from 1 to floor(i/j)
now the subsets with a common divisor(and not GCD) as i is (2^sum - 1) .
Now we have to subtract from this sum the subsets with GCD greater than i and having i as a common divisor of gcd as i.
This can also be done within the same loop by taking summation of f2[i*j] where j varies from 1 to floor(i/j)
Now the subsets with GCD i equal to 2^sum -1 - summation of f2[ij] Just multiply i ( No . of subsets with GCD i times ) i.e. power ( i , 2^sum -1 - summation of f2[ij] ) . But now to calculate this the exponent part can overflow but you can take its % with given MOD-1 as MOD was prime! (Fermat little theorem) using modular exponentiation
Here is a snippet of my code as I am unsure that can we post the code now!
for(i=max_ele; i >= 1;--i)
{
to_add=F[i];
to_subtract = 0 ;
for(j=2 ;j*i <= max_ele;++j)
{
to_add+=F[j*i];
to_subtract+=F2[j*i];
to_subtract>=(MOD-1)?(to_subtract%=(MOD-1)):0;
}
subsets = (((power(2 , to_add , MOD-1) ) - 1) - to_subtract)%(MOD-1) ;
if(subsets<0)
subsets = (subsets%(MOD-1) +MOD-1)%(MOD-1);
ans = ans * power(i , subsets , MOD);
F2[i]= subsets;
ans %=MOD;
}
I feel like I had complicated the things by using F2, I feel like we can do it without F2 by not taking j = 1. but it's okay I haven't thought about it and this is how I managed to get AC .
zero-indexed array A consisting of N integers is given. A triplet (P, Q, R) is triangular if and
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
For example, consider array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
Triplet (0, 2, 4) is triangular.
Write a function
int triangle(const vector<int> &A);
that, given a zero-indexed array A consisting of N integers, returns 1 if there exists a triangular triplet for this array and returns 0 otherwise.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range [-2,147,483,648..2,147,483,647].
For example, given array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
the function should return 1, as explained above. Given array A such that
A[0] = 10 A[1] = 50 A[2] = 5
A[3] = 1
the function should return 0.
Expected worst-case time complexity:
Expected worst-case space complexity: O(1)
First claim
First of all there is no point to take into account non-positive number. There's no chance you may achieve the triangle inequalities if at least one of the numbers is negative or zero. This is obvious, nevertheless here is the proof:
Assume A, B, C obey the triangle inequality, whereas C <= 0. Then you have
A + C > B. Hence A > B.
B + C > A. Hence B > A.
(contradiction).
Second claim
Suppose A, B, C obey the triangle inequalities, whereas C is the largest among A,B,C. Then for each A2 and B2 between A,B respectively and C - they will also obey triangle inequality.
In other words:
A,B,C obey triangle inequalities.
C >= A
C >= B
C >= A2 >= A
C >= B2 >= B
Then A2,B2,C also obey triangle inequalities.
The proof is trivial, enough to write the inequalities explicitly.
The consequence of this is that if C is the largest number for which you want to find the triangle inequality - you should check only two largest numbers from the set not exceeding C, and check if A + B > C.
Third claim
If 0 < A <= B <= C don't obey triangle inequalities, then C >= A*2.
The proof is trivial as well: A + B <= C, hence A + A <= C, hence C >= A*2
The algorithm
Pick 2 largest numbers B and C (B <= C).
Pick the largest number A not exceeding B, such that
A <= B <= C.
Make sure it's not the same element as B,C
Take into account only positive integers.
If unable to pick such a number - done. (No triangulars).
Check if A,B,C obey the triangle inequality. Test if A + B > C. (done if they do).
Discard the largest number C. Substitute C = B, then B = A.
Go to step 2.
Fourth claim
The above algorithm is logarithmic in the maximum integer size. In other words, its linear in the data type bitness. It's worst-case complexity is independent on the input length. Hence - it's O(1) in the input length.
Proof:
At every iteration (that does not find the solution) we have A <= C/2. After two such iterations A becomes the new C. This means that after every two iterations the largest number becomes at least 2 times smaller.
Obviously this gives us the upper bound of the number of the iterations. Gives our integers are limited by 31 bit (we ignore negatives), whereas the minimum interesting largest C is 1, this gives us no more that 2 * (31 - 1) = 60 iterations.
If O(N³) is acceptable time complexity then the Pseudocode below should work. If you have stricter time complexity requirements then you'll have to specify them.
for (P in A){
for (Q in A){
for (R in A){
if(A[P] > 0 && A[Q] > 0 && A[R] > 0){
if(A[P] > A[R] - A[Q] && A[Q] > A[P] - A[R] && A[R] > A[Q] - A[P]){
return 1;
}
}
}
}
}
return 0;
The reasoning behind the if statements is this:
Since the ints can be anything up to max int you have to deal with overflow. Adding them together could cause a weird error if there are two very large ints in the array. So instead we test if they are positive and then rewrite the formulae to do the same checks, but with subtraction. We don't need to do anything if any of the values are negative or 0, since:
Assume x <= 0
Assume x+y > z
Assume x+z > y
Then y > z and z > y which is a contradiction
So no negative or zero valued ints will be a part of a triple
Sorting would be very cool, but const vector and O(1) space requirements doesn't allow it.
(because this is homework) Some hint: triangular numbers are close to each other.
A hint: if you pick just two members of the array then what are the limits on the possible value of the third member of a triangular triplet? Any number outside those limits can be rejected immediately.
There are many in-place sorts; use one of them to sort the array - say comb sort for smaller ones (time complexity O(N^2)) or heap sort (complexity O(N log(N)).
Once you have sorted array, problem should be whether there is a set of 3 numbers where A[X] > (A[X-1] + A[X+1]) / 2 i.e. middle number is greater than average of preceding & succeeding numbers (sadly this is a guess, I don't have a real basis - if its incorrect I hope someone corrects me, but there should be some good way to redefine the 'triangle' requirement to be more easily checked).
Now you just have an O(1) iteration over the sorted array to check whether the condition is true, hence overall complexity will be that of the sorting algorithm (best case N logN)
zero-indexed array A consisting of N integers is given. A triplet (P, Q, R) is triangular if and
A[P] + A[Q] > A[R],
A[Q] + A[R] > A[P],
A[R] + A[P] > A[Q].
For example, consider array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
Triplet (0, 2, 4) is triangular.
Write a function
int triangle(const vector<int> &A);
that, given a zero-indexed array A consisting of N integers, returns 1 if there exists a triangular triplet for this array and returns 0 otherwise.
Assume that:
N is an integer within the range [0..100,000];
each element of array A is an integer within the range [-2,147,483,648..2,147,483,647].
For example, given array A such that
A[0] = 10 A[1] = 2 A[2] = 5
A[3] = 1 A[4] = 8 A[5] = 20
the function should return 1, as explained above. Given array A such that
A[0] = 10 A[1] = 50 A[2] = 5
A[3] = 1
the function should return 0.
Expected worst-case time complexity:
Expected worst-case space complexity: O(1)
First claim
First of all there is no point to take into account non-positive number. There's no chance you may achieve the triangle inequalities if at least one of the numbers is negative or zero. This is obvious, nevertheless here is the proof:
Assume A, B, C obey the triangle inequality, whereas C <= 0. Then you have
A + C > B. Hence A > B.
B + C > A. Hence B > A.
(contradiction).
Second claim
Suppose A, B, C obey the triangle inequalities, whereas C is the largest among A,B,C. Then for each A2 and B2 between A,B respectively and C - they will also obey triangle inequality.
In other words:
A,B,C obey triangle inequalities.
C >= A
C >= B
C >= A2 >= A
C >= B2 >= B
Then A2,B2,C also obey triangle inequalities.
The proof is trivial, enough to write the inequalities explicitly.
The consequence of this is that if C is the largest number for which you want to find the triangle inequality - you should check only two largest numbers from the set not exceeding C, and check if A + B > C.
Third claim
If 0 < A <= B <= C don't obey triangle inequalities, then C >= A*2.
The proof is trivial as well: A + B <= C, hence A + A <= C, hence C >= A*2
The algorithm
Pick 2 largest numbers B and C (B <= C).
Pick the largest number A not exceeding B, such that
A <= B <= C.
Make sure it's not the same element as B,C
Take into account only positive integers.
If unable to pick such a number - done. (No triangulars).
Check if A,B,C obey the triangle inequality. Test if A + B > C. (done if they do).
Discard the largest number C. Substitute C = B, then B = A.
Go to step 2.
Fourth claim
The above algorithm is logarithmic in the maximum integer size. In other words, its linear in the data type bitness. It's worst-case complexity is independent on the input length. Hence - it's O(1) in the input length.
Proof:
At every iteration (that does not find the solution) we have A <= C/2. After two such iterations A becomes the new C. This means that after every two iterations the largest number becomes at least 2 times smaller.
Obviously this gives us the upper bound of the number of the iterations. Gives our integers are limited by 31 bit (we ignore negatives), whereas the minimum interesting largest C is 1, this gives us no more that 2 * (31 - 1) = 60 iterations.
If O(N³) is acceptable time complexity then the Pseudocode below should work. If you have stricter time complexity requirements then you'll have to specify them.
for (P in A){
for (Q in A){
for (R in A){
if(A[P] > 0 && A[Q] > 0 && A[R] > 0){
if(A[P] > A[R] - A[Q] && A[Q] > A[P] - A[R] && A[R] > A[Q] - A[P]){
return 1;
}
}
}
}
}
return 0;
The reasoning behind the if statements is this:
Since the ints can be anything up to max int you have to deal with overflow. Adding them together could cause a weird error if there are two very large ints in the array. So instead we test if they are positive and then rewrite the formulae to do the same checks, but with subtraction. We don't need to do anything if any of the values are negative or 0, since:
Assume x <= 0
Assume x+y > z
Assume x+z > y
Then y > z and z > y which is a contradiction
So no negative or zero valued ints will be a part of a triple
Sorting would be very cool, but const vector and O(1) space requirements doesn't allow it.
(because this is homework) Some hint: triangular numbers are close to each other.
A hint: if you pick just two members of the array then what are the limits on the possible value of the third member of a triangular triplet? Any number outside those limits can be rejected immediately.
There are many in-place sorts; use one of them to sort the array - say comb sort for smaller ones (time complexity O(N^2)) or heap sort (complexity O(N log(N)).
Once you have sorted array, problem should be whether there is a set of 3 numbers where A[X] > (A[X-1] + A[X+1]) / 2 i.e. middle number is greater than average of preceding & succeeding numbers (sadly this is a guess, I don't have a real basis - if its incorrect I hope someone corrects me, but there should be some good way to redefine the 'triangle' requirement to be more easily checked).
Now you just have an O(1) iteration over the sorted array to check whether the condition is true, hence overall complexity will be that of the sorting algorithm (best case N logN)