大整数乘法
题目描述
使用分治算法实现两个大整数相乘。
算法分析
使用分治解决两个位数为2的N次方倍的大整数相乘:
分析:
看起来好像有点变化,分析一下:对这个式子,我们一共要进行4次 n / 2的乘法(AC2次, AD, BC)和 3次加法,因而该算法的时间复杂度为:
T(n) = 4 * T(n / 2) + θ(n)
通过master定理可以求得 T(n) = θ(n ^ 2),跟小学算法的时间复杂度没有区别。
改进:
但是我们再来看看,我们是否可以用加法来换取乘法?因为多一个加法操作,也是常数项,对时间复杂度没有影响,如果减少一个乘法则不同。
现在的时间复杂度为:
T(n) = 3 * T(n / 2) + θ(n),通过master定理求得,T(n) = O(n^log2(3) ) = O(n^1.59 )。
输入
两个十进制大整数,满足每一个整数长度为2^n且两个大整数的长度相等。(多组数据)
输出
两个大整数的乘积。
样例输入
1234 5678
样例输出
7006652
Code
package Week8;
import java.util.Scanner;
//两个十进制大整数,满足每一个整数长度为2^n且两个大整数的长度相等
public class QB {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
//DecimalFormat df = new DecimalFormat("######0");
while(sc.hasNext()){
long num1,num2;
num1 = sc.nextInt();
num2 = sc.nextInt();
int sum_n1,sum_n2;
sum_n1 = sum_len(num1);
sum_n2 = sum_len(num2);
// System.out.println(sum_n1);
// System.out.println(sum_n2);
if(sum_n1==sum_n2){
if(!(Judge(sum_n1)&&Judge(sum_n2))){
System.out.println(Calculate(num1,num2,sum_n1));
}
}
}
}
//判断整数位数是否为2的n次方
public static boolean Judge(int n){
if(n<=1){
return true;
} else {
if(n%2==0){
n/=2;
Judge(n);
}
}
return false;
}
//计算整数长度
public static int sum_len(double n){
int sum = 0;
for(double i=n;i>1;i/=10){
sum++;
}
return sum;
}
//建立一个符号函数
public static int sign(double n){
return n>0?1:-1;
}
public static long Calculate(long x,long y,int n){
//符号位
int sign = sign(x)*sign(y);
x = Math.abs(x);
y = Math.abs(y);
if(x==0||y==0){
return 0;
}else if(n==1){
return sign*x*y;
}else {
//Math.pow的计算结果默认类型为double
long A = (long) (x/ Math.pow(10,n/2));
long B = (long) (x%Math.pow(10,n/2));
long C = (long) (y/Math.pow(10,n/2));
long D = (long) (y%Math.pow(10,n/2));
long AC = Calculate(A,C,n/2);
long BD = Calculate(B,D,n/2);
// //System.out.println((A-B)*(D-C));
// System.out.println(AC);
long ABDC = Calculate((A - B), (D - C), n / 2) + AC + BD;
return (long) (sign * ((AC * Math.pow(10 ,n) + ABDC * Math.pow(10, (n / 2)) + BD)));
}
}
}