求多個正整數的最大公約數和最小公倍數的三種演算法

來源:互聯網
上載者:User

第一種:分解質因數法

import java.util.HashSet;import java.util.HashMap;import java.util.Map;import java.util.Iterator;import java.util.Scanner;/* *@topic:多個正整數的最大公約數和最小公倍數——分解質因數法 *//* *  756 = 2*2*3*3*3*7 *504 = 2*2*2*3*3*7 *630 = 2*3*3*5*7 *2226 = 2*3*7*53 *最大公約數為4個數的公因子相乘:2*3*7 = 42 *最小公倍數為4個數不重複因子相乘:2*2*2*3*3*3*5*7*53 = 400680 */public class GcdLcm {static int[] a;//存放正整數static int n;//正整數個數static int[] prime = new int[1000];//素數表static HashSet<Integer> qf = new HashSet<Integer>();//存放所有因子static HashMap<Integer, Integer> df = new HashMap<Integer, Integer>();//存放重複因子及其個數public static void main(String[] args) {// System.out.println("Hello Landor!");for (int i = 1, j = 0; j < 1000; i++) {if (isPrime(i))prime[j++] = i;}// 建立素數表Scanner sc = new Scanner(System.in);n = sc.nextInt();a = new int[n];for (int i = 0; i < n; i++)a[i] = sc.nextInt();calculate();System.out.println("最大公約數為:" + getGcd());System.out.println("最小公倍數為:" + getLcm());}public static void calculate() {//依次將每個正整數進行因數分解:756 = 2*2*3*3*3*7int i, j, count = 0;for (i = 0; i < n; i++) {int m = a[i];for (j = 0; j < 1000 && m > 1; j++) {Integer key = new Integer(prime[i]);while (m % prime[j] == 0) {m /= prime[j];qf.add(key);//將此因數放進HashSet中(會自動去重)count++;}if (count > 0) {if (df.get(key) == null) {//如果此因數沒有出現過,則直接將因數及其個數放入HashMap中df.put(key, new Integer(count));} else if (df.get(key).intValue() < count) {df.remove(key);//如果出現此因數的個數比hashmap中的個數大,則刪除後將新的個數添加df.put(key, new Integer(count));}}count = 0;}}}public static int getGcd() {int gcd = 1, i, j;Iterator<Integer> it = qf.iterator();while (it.hasNext()) {//遍曆每個qf中的因數,若為公因數則與gcd相乘i = it.next().intValue();for (j = 0; j < n; j++) {if (a[j] % i != 0)//不是公因數break;}if (j == n)gcd *= i;}return gcd;}public static int getLcm() {int lcm = 1;//System.out.println(df);for (Map.Entry<Integer, Integer> e : df.entrySet())lcm *= (int) Math.pow((double) e.getKey().intValue(), (double) e.getValue().intValue());//遍曆HashMap中的Key和Value,將Key的Value次方與lcm相乘return lcm;}public static boolean isPrime(int n) {// 判斷素數int i, step = 4, s = (int) Math.sqrt((double) n + 0.01);if (n < 1)System.exit(1);if (n == 2 || n == 3)return true;if (n == 1 || n % 2 == 0 || n % 3 == 0)return false;for (i = 5; i <= s; i += step) {if (n % i == 0)break;step ^= 6;}return i > s;}}/* 測試執行個體:47565046302226最大公約數為:42最小公倍數為:400680*/

 

第二種:輾轉相除遞推法

import java.util.Scanner;/* *@topic:多個正整數的最大公約數和最小公倍數——輾轉相除遞推法 *//* *  先求gcd: *(756,504):756%504 = 252 ,504%252 = 0 ,所以(756,504)=252 *(630,252):630%252 = 126 ,252%126 = 0, 所以(630,252)=126 *(2226,126):2226%126 = 84,126%84 = 42,84%42=0,所以(2226,126)=42 *所以4個數的最大公約數為:(756,504,630,2226)=42 *再求lcm: *[756,504]=756*504/252=1512 *[1512,630]=1512*630/126=7560   注意,此處的126和上面所求126沒有關係,這裡的126是需要求gcd(1512,630)得到的 *[7560,2226]=7560*2226/42=400680 *所以4個數的最小公倍數為:[756,504,630,2226]=400680 */public class GcdLcm1 {static int[] a;// 存放正整數static int n;// 正整數個數public static void main(String[] args) {// System.out.println("Hello Landor!");Scanner sc = new Scanner(System.in);n = sc.nextInt();a = new int[n];for (int i = 0; i < n; i++)a[i] = sc.nextInt();System.out.println("最大公約數為:" + getGcd());System.out.println("最小公倍數為:" + getLcm());}public static int getGcd() {int p = a[0];for (int i = 1; i < n; i++)p = gcd(Math.max(p, a[i]), Math.min(p, a[i]));return p;}public static int getLcm() {int lcm = a[0];for (int i = 1; i < n; i++)lcm *= (a[i] / gcd(Math.max(lcm, a[i]), Math.min(lcm, a[i])));return lcm;}public static int gcd(int x, int y) {return (y == 0) ? x : gcd(y, x % y);}}

第三種:逐次想減、相除法

逐次相減是用來求最大公約數的,是輾轉相除的一種推廣

演算法描述:

     先將m個數由大到小排序,再逐次相減修改各元素的值。設排序後相鄰的兩個數為A、B(A≥B)。再設n=1、2、3.....,各個A同步選取述方法重新賦值:

       如A>n*B ,則A=A-n*B>0,n是滿足條件的最大整數,相當於A=A%B;

       如A=B,A不變;

       如A=n*B,n≠1,則A=A-(n-1)*B,即取A=B,A不能小於1;

   例如:求最大公約數(756,504,630,2226)

   ①4個數排序,再從左至右逐次相減:

           (756,504,630,2226)=(2226,756,630,504)=(2226-2*756,756-630,630-504,504)=(714,126,126,504)

   ②再排序,逐次相減:

           (714,126,126,504)=(714,504,126,126)=(210,504-3*126,126,126)=(210,126,126,126)

   ③再排序,逐次相減:

            (210,126,126,126)=(84,126,126,126)=(126,126,126,84)=(126,126,42,84)=(126,126,84,42)=(126,42,42,42)

                                                            =(126-2*42,42,42,42)=(42,42,42,42)

    此時,四個數相同,完畢,最大公約數為42

   

main(){long a[4]={756,504,630,2226},i,j,t;printf("最大公約數:(%ld,%ld,%ld,%ld)\n",a[0],a[1],a[2],a[3]);h:for(i=0;i<3;i++){for(j=i+1;j<=3;j++)if(a[i]<a[j]){t=a[i];a[i]=a[j];a[j]=t;}}printf("=(%ld,%ld,%ld,%ld)\n",a[0],a[1],a[2],a[3]);if(a[0]==a[3]){printf("=%ld\n\n",a[0]);exit(0);}else{for(i=0;i<3;i++){if(a[i]%a[i+1]!=0)a[i]=a[i]%a[i+1];elsea[i]=a[i+1];}printf("=(%ld,%ld,%ld,%ld)\n",a[0],a[1],a[2],a[3]);goto h;}}

逐次相除:用來求最小公倍數

設有若干數,其中最大的為a,用a的1倍、2倍、3倍、…,除以其餘的各數,若第n次恰好都除盡,則此時的n*a即為它們的最小公倍數

這個演算法比較SB,就不貼代碼了,有興趣自己寫一下。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.