學習分治法+解決大數乘法問題

大整數乘法

分治法

將一個規模爲N的問題,分解成K個規模較小的子問題,這些子問題相互獨立且月原問題性質相同,求解出子問題的解,合併獲得原問題的解java

java中的BigInteger總結

(1)程序有時須要處理大整數,java.math包中的BigInteger類提供任意精度的整數運算,可使用構造方法:算法

public BigInteger(String VAL)構造一個十進制的BigInteger對象,該構造方法能夠發生NumberFormatException異常,也就是說,字符串參數VAL中若是含有非數字字符就會發生NumberFormatException異常。數組

(2)BigInteger類的經常使用方法:ide

public BigInteger add(BigInteger val) 返回當前大整數對象與參數指定的大整數對象的和code

public BigInteger subtract(BigInteger val) 返回當前大整數對象與參數指定的大整數對象的差orm

public BigInteger multiply(BigInteger val) 返回當前大整數對象與參數指定的大整數對象的積對象

public BigInteger devide(BigInteger val) 返回當前大整數對象與參數指定的大整數對象的商遞歸

public BigInteger remainder(BigInteger val) 返回當前大整數對象與參數指定的大整數對象的餘ip

public int compareTo(BigInteger val) 返回當前大整數對象與參數指定的大整數對象的比較結果,返回值是一、-一、0,分別表示當前大整數對象大於、小於或等於參數指定的大整數。ci

public BigInteger abs() 返回當前大整數對象的絕對值

public BigInteger pow(int exponent) 返回當前大整數對象的exponent次冪。

public String toString() 返回當前當前大整數對象十進制的字符串表示。

public String toString(int p) 返回當前大整數對象p進制的字符串表示。

可是這篇文章不用這個java內置的方法來實現大數乘法

import java.util.*;
 import java.math.*;
  
 public class NumMul{
      public static void main(String args[]){
          Scanner cin = new Scanner(System.in);
          BigInteger a, b;
          while(cin.hasNext()){
              a = cin.nextBigInteger();
             b = cin.nextBigInteger();
            System.out.println(a.multiply(b));
         }
    }
 }

分治算法特徵分析

分治法能解決的問題通常具備如下幾個特徵:

  1. 該問題的規模縮小到必定程度就能夠容易的解決;

  2. 該問題能夠分解爲若干個規模較小的相同問題,即該問題具備最優子結構性質;

  3. 利用該問題分解出子問題的解,能夠合併爲該問題的解;

  4. 該問題所分解出的各個子問題是相互獨立的,即子問題之間不包含公共的子子問題;

分治算法大多采用遞歸實現,第二條特徵就反應了遞歸思想的引用。

若是知足了第一條特徵和第二條特徵,不知足第三條特徵,能夠考慮用貪心法或動態規劃法。

若是不知足第四條特徵,也能夠用分治法,可是要作不少沒必要要的工做,重複的解公共的子問題,因此通常用動態規劃法比較好。

大整數乘法:十進制

解法一(分治法)

將兩個整數分別一分爲二:

X = A*10^(n/2) + B

Y = C*10^(n/2) + D

X*Y =  (A*10^(n/2) + B)*( C*10^(n/2) + D) =  A*C*10^n + A*D*10^(n/2) + B*C*10^(n/2) + B*D

可是這樣作並無減小直接相乘的的時間複雜度,因此要繼續減小乘法的次數

X*Y = (A*10^(n/2) + B)*( C*10^(n/2) + D)

    = A*C*10^n + A*D*10^(n/2) + B*C*10^(n/2) + B*D

    = A*C*10^n + ((A+B)(C+D) – A*C – B*D)*10*(n/2) + B*D

或者:= A*C*10^n + ((A-B)(D-C) + A*C + B*D)*10*(n/2) + B*D

而後利用上面的公式寫遞歸就行了

代碼以下:

public class BigDataRide {
 
	public static int sign(long a) {
 
		return a < 0 ? -1 : 1;
 
	}
 
	public static double bigdataride(long x,long y,int n) {
 
		x = Math.abs(x);
 
		y = Math.abs(y);
 
		if (n == 1) {
			
			return x * y;
 
		}
 
		else {
			if (n%2==1) {
				n = n - 1; //對奇數的操做
			}
			long a = x / Math.round(Math.pow( 10 , (n / 2)));
 
			long b = x - a * Math.round(Math.pow( 10 , (n / 2)));
 
			long c = y / Math.round(Math.pow( 10 , (n / 2)));
 
			long d = y - c * Math.round(Math.pow( 10 , (n / 2)));
 
			double ac = bigdataride(a,c,n/2);//遞歸計算a*c
 
			double bd = bigdataride(b,d,n/2);//計算b*d
 
			long aJb = a + b;
 
			long cJd = c + d;
 
			double abcd = bigdataride(aJb,cJd,n/2);
 
			return (ac*Math.pow(10,n) + (abcd - ac - bd)*Math.pow(10,n/2) +bd);
 
		}
 
	}
 
	public static void main(String[] args) {
 
		// 大整數相乘
 
		long x = 12234L;
 
		long y = 45243L;
 
		String sx = String.valueOf(x);
 
		int n = sx.length();
 
		long sig = sign(x)*sign(y);
 
		double s = bigdataride(x,y,n);
 
		System.out.println("大數相乘的計算結果爲:"+s*sig);
 
 
	}
 
}

解法二

模擬乘法

將兩個數分別存入兩個數組,而後根據乘法規則兩層for循環分別讓數字相乘,並存入一個新的數組,大體爲這樣:result[a+b] += num1[a]*num2[b];,如今這個result裏存儲的就是一個非個位數的臨時結果,只須要作後將這個臨時結果分別進位即可獲得最終結果

代碼以下:

import java.util.Scanner;

//建立類largenumberOperationMultiply
public class largenumberOperationMultiply {

    //定義方法multiply的功能
    public String multiply(String str1,String str2){
        int[] num1 = new int[str1.length()];
        int[] num2 = new int[str2.length()];
        int[] result = new int[str1.length() + str2.length()];

        //將兩個字符串轉成整型數組,順序轉換,數組下標越小,數字對應的位數越高
        for (int i = 0;i < str1.length(); i++){
            num1[i] = Integer.parseInt(str1.substring(i,i+1));
        }
        for (int i = 0;i < str2.length(); i++){
            num2[i] = Integer.parseInt(str2.substring(i,i+1));
        }

        //兩大數相乘
        for (int a = 0;a < str1.length(); a++){
            for (int b = 0;b < str2.length(); b++){
                result[a+b] += num1[a]*num2[b];
            }
        }

        ////判斷是否須要進位,滿10進1,由於存儲順序與位數高低相反,因此採用逆序進位
        int temp;
        for (int k = result.length-1; k > 0; k--){
                temp=result[k]/10;  //數組下標大的向數組下標小的進位
                result[k-1] += temp;
                result[k] = result[k]%10;
            }

        //將結果數組逆序轉化爲字符串
        String resultstr = "";
        for (int i = 0; i < result.length-1; i++){
            resultstr += "" + result[i];
        }

        return resultstr;
    }

    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入第一個數:");
        String str1 = sc.next();
        System.out.println("請輸入第二個數:");
        String str2 = sc.next();
        largenumberOperationMultiply bn = new largenumberOperationMultiply();
        //建立類largenumberOperationMultiply的對象bn
        String output = bn.multiply(str1,str2);
        //bn對象調用multiply方法對str1和str2進行操做
        System.out.println(str1+"與"+str2+"的積爲:"+output);
    }
}

來個c版本的數組實現大數乘法

#include<stdio.h>
#include<string.h>
#include<math.h>
#define N 1005
char a[N],b[N];
int s1[N],s2[N],s3[N*N];
int main()
{
    int len1,len2,max,i,j;
    while(scanf("%s%s",a,b)!=EOF)
    {
        memset(s1,0,sizeof(s1));
        memset(s2,0,sizeof(s2));
        memset(s3,0,sizeof(s3));
        len1=strlen(a);
        len2=strlen(b);
        max=0;
        max=len1+len2;
        for(i=0,j=len1-1;i<len1;i++,j--)
            s1[i]=a[j]-'0';
        for(i=0,j=len2-1;i<len2;i++,j--)
            s2[i]=b[j]-'0';
        for(i=0;i<len1;i++)
            for(j=0;j<len2;j++)
                s3[i+j]+=s1[i]*s2[j];
        for(i=0;i<max;i++)
        {
            if(s3[i]>=10)
            {
                s3[i+1]+=s3[i]/10;
                s3[i]%=10;
            }
        }
        while(s3[max-1]==0)
        {
            if(s3[max-1]==0)
                max--;
        }
        for(i=max-1;i>=0;i--)
            printf("%d",s3[i]);
            printf("\n");
    }
    return 0;

}
相關文章
相關標籤/搜索