To be on safe side, we can first get a larger possible value (upper bound) and a smaller possible value (lower bound) and than reduce it to our actual answer, this way it will be accurate and faster that just iterating over numbers.
By solving the inequality we get,
N > u * p / (s - q) + 1
Getting an upper bound
So you will first find a maximum guessed answer, by using integers. We will increase numerator and integer cast denominator
int UP = (int)(u * p + 1); // Increase by one
int D = (int)(s - q); // we don't increase this because it would cause g to decrease, which we don't want
float g = UP / (float)D + 1; // we again float cast D to avoid integer division
int R = (int)(g + 1); // Now again increase g
/******** Or a more straight forward approach ********/
int R = (int)(((int)(u*p+1))/(s-q) + 1 + 1)
// Add rounding-off error here
if(R + 128 < 0) R = 2147483647; // The case of overflow
else R += 128;
This is your maximum answer (upper bound).
Getting a lower bound
Just as previous but this time we will increase denominator and integer cast numerator
int UP = (int)(u * p); // will automatically decrease
int D = (int)(s - q + 1); // we increase this because it would cause g to decrease, which we want
float g = UP / (float)D + 1; // we again float cast D to avoid integer division
int L = (int)g; // Integer cast, will automatically decrease
/******** Or a more straight forward approach ********/
int L = (int)(((int)(u*p))/(s-q+1) + 1)
// Subtract rounding-off error
if(L - 128 <= 1 ) L = 2; // N cannot be below 2
else L -= 128;
This is your minimum answer (lower bound).
Note: The reason of integer casting is to reduce our sample space. It can be omitted if you feel so.
Elimination of possible numbers and getting the right one
for (int i = L; i <= R; ++i){
if ((s > q + u*p/(i-1))) break; // answer would be i
}
N = i; // least number which satisfies the condition
You can do it even faster with binary search if the gap between bounds (R-L) is large. As for number-range whose difference is 2^n can be reduced in only n steps.
// we know that
// lower limit = L;
// upper limit = R;
// Declare u, p, q, s in global space or pass as parameters to biranySearch
int binarySearch(int l, int r)
{
if(l==r) return l;
if (r > l) {
int mid = l + (r - l) / 2;
bool b = (s > q + (p*u)/(mid-1));
if (b==true){
// we know that numbers >= mid will all satisfy
// so our scope reduced to [l, mid]
return binarySearch(l, mid);
}
// If mid doesn't satisfy
// we know that our element is greater than mid
return binarySearch(mid+1, r);
}
}
int main(void)
{
// calculate lower bound L and upper bound R here using above methods
int N = binarySearch(L, R);
// N might have rounding-off errors, so check for them
// There might be fluctuation of 128 [-63 to 64] so we will manually check.
// To be on safe side I will assume fluctuation of 256
L = N-128 > 2 ? N-128 : 2;
R = N+128 < 0 ? 2147483647 : N+128;
for(int i=L; i<=R; ++i){
if( s > q + u * p / ((float)i - 1)) {
break;
}
}
cout << i << endl;
}
It is mostly a concept, but it is fast and safe. The only thing is that I have not tested it, but it should work!