[Algorithm diary] Recursive realization of large integer multiplication branch

Problem description : As the title shows, it is the multiplication of two large integers. Sometimes if the value is too large, the computer cannot directly calculate it, and the idea of ​​branching needs to be used.
The basic idea of ​​the divide-and-conquer algorithm is to decompose a problem with a scale of N into K smaller-scale sub-problems, which are independent of each other and have the same properties as the original problem. Find the solution of the sub-problem, and then the solution of the original problem can be obtained. That is to say, an algorithm for completing the program by dividing the goal. Generally, it will be solved by dichotomy ( there are many online materials, so I won't repeat it here ).
Scenario assumption : Suppose there are two large integers X and Y, set X=1234 and Y=6789 respectively. Now the product of X*Y is required. The algorithm of elementary school is to multiply each item in X and Y, but the time complexity required for such a multiplication is O(N^2), (because each bit has to go one by one Multiply), so the efficiency is relatively low. Then we can use the divide and conquer algorithm to split X and Y into four parts, as shown below:
Insert picture description here

In this way, X can be expressed as Insert picture description here
Y in the same way, so Y=C*10^(n/2)+D;
(some information books say X=A**2^(n/2)+B, because it It is expressed in binary, and here is written in decimal.)
So now we divide a large integer into two parts, and the problem size is reduced, so that the direct multiplication will be written as. Insert picture description here
But then you will find that you still have to calculate 4 times in the end. /2 multiplication of integers, and three additions, according to the master theorem, you will find that T(n)=O(n^2); So this is actually not improved. To improve, you need to reduce the multiplication by deforming the formula For this, we write the following form: Insert picture description here
This can reduce the number of multiplications, (only AC, BD (AB) (DC) three multiplications are done), by the master theorem, T(n)=O(n^ log3), the optimization is successful.
The test code is as follows:


#include<cstdio>
#include<cmath>

using namespace std;

#define SIGN(A) ((A > 0) ? 1 : -1) 
int divideConquer(int X, int Y, int n) {
	int sign = SIGN(X) * SIGN(Y);
	int x = abs(X);
	int y = abs(Y);
	if (x == 0 || y == 0) {
		return 0;
	}
	else if (n == 1) {
		return sign * x * y;
	}
	else {
		int A = (int)x / pow(10, (int)(n / 2));
		int B = x - A * pow(10, n / 2);
		int C = (int)y / pow(10, (int)(n / 2));
		int D = y - C * pow(10, n / 2);
		int AC = divideConquer(A, C, n / 2);
		int BD = divideConquer(B, D, n / 2);
		int ABDC = divideConquer((A - B), (D - C), n / 2) + AC + BD;
		return sign * (AC * pow(10, n) + ABDC * pow(10, (int)(n / 2)) + BD);
	}
}

int main() {
	int x, y, n;
	scanf_s("%d%d%d", &x, &y, &n);
	printf("x 和 y的乘积为:%d", divideConquer(x, y, n));
}

Guess you like

Origin blog.csdn.net/wdxyxshark/article/details/108762552