I solved 986F - Oppa Funcan Style Remastered today and faced the following problem.
You had to solve a linear diophantine equation:
This is of course quite easy, with the extended Euclidean algorithm you can find a solution:
and by multiplying with c / g gives a final solution:
And all solutions can be written as
The problem is, that this can easily give an integer overflow. E.g. when a, b and c are as large as 1018. To solve the problem I just took my BigInteger implementation. But this is of course quite ugly (400 additional lines of code just for one simple calculation).
How can we avoid the overflow? I want a solution for a·x + b·y = c with |x|, |y| ≤ 1018.
I found the following code in the solution of tourist. But I'm unable to wrap my head around it. Can somebody explain me the logic of this formula?
g = extgcd(a, b, x, y);
if (c % g != 0) {
return false;
}
long long dx = c / a;
c -= dx * a;
long long dy = c / b;
c -= dy * b;
x = dx + mulmod(x, c / g, b);
y = dy + mulmod(y, c / g, a);
g = abs(g);
Exactly same question, but I gave up and just copied it
Note: Oversized LaTeX doesn't work for me right now, so some of the formulas are ugly.
The lines with
dx, dy
reduce to the case where |c| < min(|a|, |b|). (If |c| ≥ |a|, we can subtract/add (depending on signs) a from c and increment/decrement x by one in the end and similarly for |b| and y.)Note that his
mulmod
function computes a·b mod c with sign, so if a·b is negative, so is the results. This part does need 128 bit multiplication, done in thewhile(b>0)
, but it's simpler than a full blown big-integer implementation.In the last part, he computes X: = x0·c / g, X': = X mod b and Y: = y0·c / g, Y': = Y mod a, so we don't get equality right away (X, Y are not computed in his code, but I'll use then in my equations.). Instead we get the congruence
If Y' = 0, then a divides c, hence c = 0. This implies 0 = X = X'. The case X' = 0 implies c = 0 and Y' = 0 in similar fashion. The cases with a = 0 or b = 0 are treated separately elsewhere in his code, so we can ignore then here.
Note that if X·a and Y·b have the same sign (not sure if this can happen actually), we get the inequality
hence X = X' and by symmetry Y = Y', so we get equality, not only ≡ .
The case where X·a and Y·b have opposite sign is more tricky. W.l.o.g let X·a > 0 > Y·b and assume C: = X'·a + Y'·b > c. From the congruence, we get C ≥ c + |ab|. Note that
as |c| < |b| ≤ |Y'b| and Y'b < 0 by sign preservation in the computation of Y'. Therefore
Hence |X'| ≥ |b| contradiction. The case C < c is similar and leads to |Y'| > |a| contradiction. Therefore c = C', this proves correctness.
Thanks for the proof. Where is the 128-bit multiplication done in his solution?