-4

following Problem, when having to make a fast code: I have a list of 2 integers a_i and b_i and I have to compute the equation: y = (a_i * x + b_i), where I'm only interested in y, not in x. All a_i's are prime and different from each other. a_i = y / x, b_i = y % x.

There are multiple solutions for y, even if y has to be the same for all a_i, b_i pairs, as x can be any integer number. Therefore we have an upper limit k and y <= k. I want to have the highest y possible (if there is a solution). max(y).

In short: I want to know the highest integer y (if there exists one), with y <= k and the equation given. x >= 1.

I already have a "solution" that works in theory, but that is too slow:

struct part {
unsigned int size, rest;
};

int solve(vector<part> &partions, int minK, int stepSize, int k) {
    int sol = 0;

    for (int i = k; i >= minK; i -= stepSize) {
        bool works = true;
        for (int j = 0; j < static_cast<int>(partions.size()); j++) {
            if ((i - partions[j].rest) % partions[j].size != 0) {
                works = false;
                break;
            }
        }
        if (works) return i;
    }



    return -1;
}

Explanation: minK is max(a_i + b_i), as I thought that y = a_i *1 + b_i is the smallest possible solution for one equation, and as y is the same for all equations, the maximum one is the best lower bound.

stepSize is not 1 (in order to make the program faster), but max(a_i), as I thought, that as max(a_i) has to fit in y and y = a_i * x + b_i, therefore as x are integer values, the stepSize is a_i, and max(a_i) the best one, because that decreases the number of loop runs.

I now try out all y's from k to minK with stepSize and test for all pairs a_i and b_i, if they fulfill the equation. If one of them fails, I have to go on until I either find a solution or none (-1).

Unfortunately that algorithm is too slow (as a_i and b_i can go up to 10^12) and I can't think of any more optimizations. I already searched the internet for number theory and arithmetic's, but couldn't find any similar thing.

Can you help me to make this code faster or hint me to some sites, where this problem is handled?

Timotheus
  • 111
  • 6
  • Once you have a `y` which satisfies all equations, every (and only) `y + Least_common_multiple(a_i...) * x` does too. – Jarod42 Jun 23 '15 at 07:34
  • @Jarod42 Once I have a y which satisfies all equations I'm done, there is no optimization there then, I need a faster way to find y. What's y + Least_common_multiple(a_i ...) * x? Why y +? Least_commom_multiple doesn't give the right answer. Imagine the pair 3, 1 and 5 2, with k = 20. The correct answer is 7. And not 15 * x + 7? – Timotheus Jun 23 '15 at 12:10
  • I means with pairs `{3, 1}, {5, 2}`, any `y = 7 + 15 * x`, so `7, 22, 37, ...` are valid. So you may find `y_max` directly (I don't know yet how to find `7` quickly though). – Jarod42 Jun 23 '15 at 14:24
  • @Jarod42 Exactly, if I have any of those values 7, 22, 37, Finding the max of them is easy. 22 mod 15 = 7, 37 mod 15 = 7, y mod 15 = y_min ---> y_max = ceil(k / y_min) * y_min The question is however, how to compute any of those y, faster than my algorithm. – Timotheus Jun 23 '15 at 22:34
  • You may look at [Modular_multiplicative_inverse](https://en.wikipedia.org/wiki/Modular_multiplicative_inverse). – Jarod42 Jun 24 '15 at 11:05

1 Answers1

0

You can satisfy for one i at a time while preserving all the ones already satisfied: step is the LCM of all the a[i] already satisfied (initially 1). y is the minimum value satisfying all the ones you did already. The key concept is that any Y satisfying all i must satisfy all the ones you already did, so it must be Y=y+n*step. So for each i you can directly compute the smallest n (if any) for which y+n*step mod a[i] equals b[i] and set y=y+n*step and step=lcm(step,a[i]). If there is no such n or if the new y is greater than k, then abort. Once you get through all i, you have the smallest y, but you wanted the largest y less than k, which is a trivial final adjustment since they differ by a multiple of step.

JSF
  • 5,156
  • 1
  • 9
  • 19
  • Jarod42's link for modular multiplicative inverse tells you how to do the one part I didn't cover in detail: How to solve for the correct n in `y+n*step mod a[i] equals b[i]` Even if you iteratively searched for that n, the performance would be much faster than the original version. But using the Extended Euclidean algorithm to find n is much faster when a[i] is large. – JSF Jul 08 '15 at 13:15
  • The original question said the a[i] are all prime, which I somewhat ignored in my answer. If all a[i] are even relatively prime, then `lcm(step,a[i])` is simple `step*a[i]` and there is no chance the n does not exist where I mentioned that possibility (there is still the chance the new minimum y is greater than k). – JSF Jul 08 '15 at 13:19