[animation notes] rolling Division — find the maximum common divisor and the minimum common multiple

Time:2022-5-6

Recently, I touched up the C language and tried to write a calculation tool in combination with the recently learned operations research. On the way, I met a demand: score reduction.

  • How to get the score in one step? The answer is to find the denominator and numeratorgreatest common divisor

  • So how to calculate the greatest common divisor as soon as possible? I checked the Internet and found an algorithm:Rolling Division

This note simply and intuitively records the algorithm.

ehe-2022-05-01

greatest common divisor

The word is very close to the scoreDivideThe so-called maximum common divisor isDivisor common to multiple integersinmaximumThe numerator and denominator when dividingAnd divide by the greatest common divisor, can getSimplest fraction

Because the process mentioned above isDivision operationSo the greatest common divisor is also calledMaximum common factor

To put it more directly,A common factor is a common divisor


There are two points to note about the definition of the greatest common divisor:

  1. Common factor / common divisor is forintegerYes.

  2. general provisions greatest common divisorbypositive integer, that is, the following formula is satisfied:

    When you want to calculate a value with a negative sign, you can put an absolute value on it and calculate it again.

Manual calculation

In reality, when calculating the maximum common divisor of multiple integers, you can list the factors of these numbers to find the common factors, or you can use short division:

shortDivision-2022-05-01

I think these methods actually depend on our previous experience, such as seeing36,405,72Zhongyou6,5,2, you may soon think of the common factor3。 (I feel that all possible factors are enumerated in my brain at this time)

If this process is abstracted into the algorithm in the programming language and implemented in code, it is probablyOne cycle+Judge whether the remainder of all numbers divided by factors is 0Yes, the time complexity isO(n), as the number of operations increases, the number of code executions increases linearly.

In order to optimize the time complexity, this time is the protagonist of this note——Rolling DivisionYes.

Rolling Division

It is mentioned above to find the maximum common divisor of multiple integers. Before that, you have to look atTwo integersBinary algorithm

formula

Rolling division is also known asEuclidean algorithm(Euclidean algorithm), how did you “toss around”? Let’s start with the formula:

Formula

ArepresentativeDivisor(Dividend);
BrepresentativeDivisor(Divisor);
A mod BOn behalf of aTake moldB. That isThe remainder of a divided by B, the expression in C language can be written asA % B

theregcdRepresentsGreatest Common Divisor, that isgreatest common divisor。 The meaning of this formula is:

  • The greatest common divisor of [divisor] and [divisor] = Maximum common divisor of [divisor] and [remainder]

This is the whole“Toss and turn”The core of the process. The specific proof will not be repeated here. You can see the at the end of the articleRelated articles


Toss and turn

Let’s demonstrate this“Toss and turn”Process, calculate36and405Maximum common factor of:

iteration-2022-05-02

So calledToss and turnActually refers to aIterative operationThe embodiment of iterative operation in programming language is actually the repeated execution of a piece of code in each execution processOperation performed last timeBased on the result value of, after calculating the new valueSubstitute into the next operation, keep usingNew value from old valueUntilUntil the termination conditions are met

The abstract description of rolling division process is as follows:

  1. initialization:Two integersMediumLarger value aAsDivisorSmaller value bAsDivisor

  2. Operations: pairAandBconductModulo (remainder) operation, getRemainder C

  3. Iteration: divide the original divisorBAsDivisor, remainderCAsDivisor, repeat the operation in step 2.

  4. Iteration termination: when an operation is in progressremainderWhen it is 0, the operation cannot be continued. The algorithm ends and the last operation is completedDivisorIs the first two integersgreatest common divisor

Intuitive understanding

At first, I thought for a while, but I didn’t think how to understand this kind of division. I didn’t understand the ancient wisdom method – geometric expression until I checked the data.

It can be thought that two integers can actually be regarded asTwo dimensions, it can be expressed by a graph in a two-dimensional space. Obviously, the most suitable figure isrectangleThe opposite sides of the rectangle are equalLength and widthTwo parameters correspond to exactly two integers.

What about the process of division? ActuallyrectangleIt’s both long and wideintegerIn the case where the aspect ratio is a rational number, it is certain to beFinite squaresFull. The process of division is actuallyInsert as large a square as possible into the rectangle


The following is a visual display of the rolling division method100and245Maximum common divisor of:

demonstration1-2022-05-02

For the first operation, take the short side 100 as the length to construct a square and fill it (as large as possible). It can be seenThe remaining rectangleThe aspect ratio is100:45That’s exactly the next operationDivisorandDivisor

demonstration2-2022-05-02

In the first iteration, a square is constructed with the short side 45 as the side length, and the remaining rectangular area is45:10, corresponding to the next iterationDivisorandDivisor

demonstration3-2022-05-02

In the second iteration, a square is constructed with the short side 10 as the side length, and the remaining rectangular area is10:5

demonstration4-2022-05-02

In the third iteration, a square is constructed with the short side 5 as the side length,It just fills the remaining rectangular area, the algorithm ends, and the maximum common divisor of the first two integers is5

  • That is, a certain number of5×5Square ofJust enough to fill100×245Rectangle (side of a square)5Just divisible100and245)。

It can be seen that the whole process of the algorithm is intuitively reflected, that is, every timeRemaining rectangular spaceInsert inSquare as large as possibleUntilThe square is just enough to fill the remaining rectangular space
(this is why the first operation divides the larger value by the smaller value)

Concrete implementation

Here, the rolling division algorithm is implemented in C language:

// #include 
long int GCD(long int num1, long int num2) {
    //Finding the greatest common divisor of two numbers (Euclidean algorithm)
    //Formula GCD (divisor, divisor) = GCD (divisor, remainder)
    //Here, in order to understand the complexity of writing, three local variables are newly defined
    long int dividend; //  Divisor
    long int divisor; //  Divisor
    long int remainder; //  remainder
    num1 = labs(num1); //  Set two numbers with absolute values
    num2 = labs(num2);
    If (num1 > num2) {// use the smaller number as the divisor
        dividend = num1;
        divisor = num2;
    } else {
        dividend = num2;
        divisor = num1;
    }
    do {
        remainder = dividend % divisor;
        dividend = divisor; //  Replace the divisor with the divisor
        If (remain) {// if the remainder is not 0, replace the divisor with the remainder
            divisor = remainder;
        }
    } while (remainder != 0);
    return divisor;
}

Time complexity

It is found that the core operation of the algorithm is“Take mold”(Modulo)。 The whole algorithm may depend on multiple iterations, and the modular operation will be carried out in each iteration, and the amount of data left for the next operation after each modular operation will be relatively reducedMore than half


Why cut it by more than half? Because every division operationremainderThe absolute value of is certainLess than half the absolute value of the divisor|Remainder | < 0.5 | divisor|

The following is a text explanation (all numbers in this picture arepositive integer):

remainderLTHalfOfDividend-2022-05-02


Anyway, mentionData halved, I can’t help thinking of two-point search. Each iteration of binary search only processes the data in the last operationhalfData. In this way, we can calculate its time complexityO(log2(n))Level (I tried before)calculationI’ve been through this.

go back toRolling Division:

(a is the divisor and B is the divisor)

twiceiterationin, a and B, respectivelyReduced by half, that is:

For divisorBFor example, every timeHalveWhen in this range:1; Therefore, the number of iterations is at most 2log (min {a, B}) (here the divisor is B, i.e. 2log (b)).

Whymin{A,B}(take the smaller value of a and b) because of the complexity of the algorithmTermination conditionsyesThe remainder is 0, it can also be understood asDivisor is 0, and the algorithm will chooselessValue of asDivisor

So the time complexity of rolling division isO(logn)Level.


For twopositive integerofRolling DivisionFor example:

  • Best case scenario

    First operationremainderThat is 0, one-step completion, and time complexity

  • Worst case scenario

    Iterate untilDivisorby1(1 is the common factor of all integers),The remainder is 0, the time complexity level is

Find the maximum common divisor of multiple integers

Rolling division is aimed atTwo integersBinary algorithm.

If the greatest common divisor of multiple integers is required, it only needs to be transformed intoMultiple binary rolling division operationJust.

C language implementation

#include 
#include   

//GCD is the binary rolling division function mentioned above

long int ArrGCD(long int *arr, int arrLen) {
    long int temp = arr[0];
    int i;
    for (i = 1; i < arrLen; i++)
        temp = GCD(temp, arr[i]); //  Use the maximum common divisor of the previous time and the current number for rolling and dividing
    return temp;
}

int main() {
    long int testArr[] = {405, 45,180,210};
    int arrLen = sizeof(testArr) / sizeof(int);
    printf("%ld\n", ArrGCD(testArr, arrLen));
    return 0;
}

Core method: useThe maximum common divisor of the previous pair of values is divided by the current number, iterate through the array.

Time complexity

The time complexity level of the previous rolling division of two integers is。 Here, you need to traverse the array elements once, andEach traversal of an element requires a rolling division algorithm

The time complexity of the algorithm for finding the maximum common divisor of multiple integers is:

Find the least common multiple

thinking-2022-05-02

The first is to find the greatest common divisorDivideThe concept of. In addition to fraction reduction, there is a very important operation skill in fraction operationGeneral points

All points are looking forLeast common multiple

On the least common multiple

Common multipleIs two integersA,BCommon multiple, i.eCommon multipleCan beAandBto be divisible by.

Of two integersCommon multipleThere are infinite numbers, and among these common multiplesExcept 0The smallest one isLeast common multipleLeast Common Multiple)。

Note: like the greatest common divisor,Least common multipleThe general rule ispositive integer


Calculate the least common multiple with the maximum convention number

After finding the greatest common divisor, finding the least common multiple is a piece of cake ~ becauseLeast common multipleandgreatest common divisorThere is one property:

NamelyLeast common multiple × Maximum common divisor = product of two integers

When the maximum common divisor is known, useProduct of two integers / maximum common divisorCan calculateLeast common multiple

PS: I won’t say much about the proof of this formula

C language implementation

The implementation here is very simple. You can call the above function for finding the maximum common divisor once.

But there is one thing to pay attention to in the program. It’s best not to write it in EnglishProduct of two integers / maximum common divisorForm of. If two integersThe values are very large, it is easy to happen in the process of calculationdata overflow Question.

In order to avoid overflow as much as possible, it can be written asA / maximum common divisor * BForm of.

long int LCM(long int num1, long int num2) {
    long int divisor = GCD(num1, num2); //  GCD is the function of finding the greatest common divisor mentioned above
    num1 = labs(num1); //  Generally, LCM is also limited to positive integer
    num2 = labs(num2);
    return (num1 / divisor) * num2; // A/GCD * B
}

Time complexity

Because the above writing is actuallyThe rolling division algorithm is appliedTherefore, the time complexity is the same:

Find the least common multiple of multiple integers

andFind the maximum common divisor of multiple integersSimilarly, it can be realized by multiple binary iterative operations.

C language implementation

long int ArrLCM(long int *arr, int arrLen) {
    long int temp = arr[0];
    int i;
    For (I = 1; I < arrlen; I + +) // traverse from the second element
        temp = LCM(temp, arr[i]); //  LCM is the function of finding the least common multiple mentioned above
    return temp;
}

Time complexity

Consistent with the above method for finding the maximum common divisor of multiple integers:

summary

ei-2022-05-02

When my head was hot, I wrote such a note. In the process of writing, I deeply realized my lack of ability in proving formulas Keep going!

In addition, I may have some problems in my understanding of the time complexity of the rolling division method. I hope you can correct it.

Related articles