From Gossip@caterpillar

Algorithm Gossip: 最大公因數、最小公倍數、因式分解

說明

最大公因數使用輾轉相除法來求,最小公倍數則由這個公式來求:
GCD * LCM = 兩數乘積

解法

最大公因數可以使用遞迴與非遞迴求解,因式分解基本上就是使用小於輸入數的數值當作除數,去除以輸入數值,如果可以整除就視為因數,例如:
  • C(不用質數表)
#include <stdio.h> 
#include <stdlib.h>

int main(void) {
int n;

printf("請輸入整數:");
scanf("%d", &n);
printf("%d = ", n);

int i;
for(i = 2; i * i <= n;) {
if(n % i == 0) {
printf("%d * ", i);
n /= i;
}
else
i++;
}

printf("%d\n", n);

return 0;
}

要比較快的解法就是求出小於該數的所有質數,並試試看是不是可以整除,求質數的問題是另一個課題,請參考 Eratosthenes 篩選求質數

實作(最大公因數、最小公倍數):C    Java    Python    Scala    Ruby

實作(使用質數表因式分解):C    Java    Python    Scala    Ruby

  • C
#include <stdio.h> 
#include <stdlib.h>

int main(void) {
int m, n;

printf("輸入兩數:");
scanf("%d %d", &m, &n);
int s = m * n;

while(n != 0) {
int r = m % n;
m = n;
n = r;
}

printf("GCD:%d\n", m);
printf("LCM:%d\n", s / m);

return 0;
}

  • Java
public class Main {
public static int gcd(int m, int n) {
if(n != 0) return gcd(n, m % n); else return m;
}
public static int lcm(int m, int n) { return m * n / gcd(m, n);}
public static void main(String[] args) {
System.out.println("GCD of (10, 4) = " + gcd(10, 4));
System.out.println("LCM of (10, 4) = " + lcm(10, 4));
}
}

  • Python
m = int(input("輸入 m:"))
n = int(input("輸入 n:"))
s = m * n
while n != 0:
r = m % n
m = n
n = r
print("GCD: ", m)
print("LCM: ", s // m)

  • Scala
def gcd(m: Int, n: Int): Int = if(n == 0) m else gcd(n, m % n)
def lcm(m: Int, n: Int) = m * n / gcd(m, n)

println("GCD of (10, 4) = " + gcd(10, 4))
println("LCM of (10, 4) = " + lcm(10, 4))

  • Ruby
# encoding: Big5
print "輸入 m:"
m = gets.to_i
print "輸入 n:"
n = gets.to_i
s = m * n
while n != 0
r = m % n
m = n
n = r
end
print "GCD: ", m, "\n"
print "LCM: ", s / m, "\n"


  • C
#include <stdio.h> 
#include <stdlib.h>

#define N 1000

int prime(int*); // 求質數表
void factor(int*, int); // 求factor

int main(void) {
int ptable[N+1] = {0};
int count, i, temp;

count = prime(ptable);

printf("請輸入一數:");
scanf("%d", &temp);
factor(ptable, temp);

printf("\n");

return 0;
}

int prime(int* pNum) {
int i, j;
int prime[N+1];

for(i = 2; i <= N; i++)
prime[i] = 1;

for(i = 2; i*i <= N; i++) {
if(prime[i] == 1) {
for(j = 2*i; j <= N; j++) {
if(j % i == 0)
prime[j] = 0;
}
}
}

for(i = 2, j = 0; i < N; i++) {
if(prime[i] == 1)
pNum[j++] = i;
}

return j;
}

void factor(int* table, int num) {
int i;
for(i = 0; table[i] * table[i] <= num;) {
if(num % table[i] == 0) {
printf("%d * ", table[i]);
num /= table[i];
}
else
i++;
}

printf("%d\n", num);
}


  • Java
import java.util.*;

public class Factor {
public static List<Integer> factor(int n) {
int num = n;
List<Integer> primes = Prime.findPrimes(num);
List<Integer> list = new ArrayList<Integer>();
for(int i = 0; primes.get(i) <= Math.sqrt(num);) {
if(num % primes.get(i) == 0) {
list.add(primes.get(i));
num /= primes.get(i);
}
else {
i++;
}
}
list.add(num);
return list;
}

public static void main(String[] args) {
for(Integer f : Factor.factor(100)) {
System.out.print(f + " ");
}
}
}

  • Python
import math

def prepare_factor(max):
prime = [1] * max
for i in range(2, int(math.sqrt(max))):
if prime[i] == 1:
for j in range(2 * i, max):
if j % i == 0:
prime[j] = 0
primes = [i for i in range(2, max) if prime[i] == 1] # 質數表

def factor(num):
list = []
i = 0
while primes[i] ** 2 <= num:
if num % primes[i] == 0:
list.append(primes[i])
num //= primes[i]
else:
i += 1
list.append(num)
f = [0] * len(list)
for i in range(len(f)):
f[i] = list[i]
return f

return factor

factor = prepare_factor(1000)
print(factor(100)) # 顯示 [2, 2, 5, 5]
print(factor(500)) # 顯示 [2, 2, 5, 5, 5]
print(factor(800)) # 顯示 [2, 2, 2, 2, 2, 5, 5]

  • Scala
def factor(n: Int) = {
var num = n
val primes = findPrimes(n)
var list: List[Int] = Nil
var i = 0
while(primes(i) <= Math.sqrt(num)) {
if(num % primes(i) == 0) {
num /= primes(i)
list = primes(i) :: list
}
else {
i += 1
}
}
num :: list
}

factor(100) foreach(f => print(f + " "))

  • Ruby
# encoding: Big5
class Range
def comprehend(&block)
return self if block.nil?
self.collect(&block).compact
end
end

def prepare_factor(max)
prime = Array.new(max, 1)
2.upto(Math.sqrt(max).to_i - 1) { |i|
if prime[i] == 1
(2 * i).upto(max - 1) { |j|
if j % i == 0
prime[j] = 0
end
}
end
}

primes = (2..max - 1).comprehend { |i| i if prime[i] == 1} # 質數表
->(num) {
list = []
i = 0
while primes[i] ** 2 <= num
if num % primes[i] == 0
list << primes[i]
num /= primes[i]
else
i += 1
end
end
list << num
f = Array.new(list.length, 0)
f.length.times { |i|
f[i] = list[i]
}
f
}
end

factor = prepare_factor(1000)
p factor.call(100) # 顯示 [2, 2, 5, 5]
p factor.call(500) # 顯示 [2, 2, 5, 5, 5]
p factor.call(800) # 顯示 [2, 2, 2, 2, 2, 5, 5]