質因數分解及演算法實現
阿新 • • 發佈:2019-01-22
每個合數都可以寫成幾個質數相乘的形式,這幾個質數就都叫做這個合數的質因數。如果一個質數是某個數的因數,那麼就說這個質數是這個數的質因數。而這個因數一定是一個質數。
定義
質因數(或質因子)在數論裡是指能整除給定正整數的質數。兩個沒有共同質因子的正整數稱為互質。因為1沒有質因子,1與任何正整數(包括1本身)都是互質。正整數的因數分解可將正整數表示為一連串的質因子相乘,質因子如重複可以指數表示。根據算術基本定理,任何正整數皆有獨一無二的質因子分解式。只有一個質因子的正整數為質數。例子
- 1沒有質因子。
- 5只有1個質因子,5本身。(5是質數。)
- 6的質因子是2和3。(6 = 2 × 3)
- 2、4、8、16等只有1個質因子:2(2是質數,4 = 2,8 = 2,如此類推。)
- 10有2個質因子:2和5。(10 = 2 × 5)
計算方法
短除法 求一個數分解質因數,要從最小的質數除起,一直除到結果為質數為止。分解質因數的算式的叫短除法,和除法的性質差不多,還可以用來求多個個數的公因式: 求最大公因數的一種方法,也可用來求最小公倍數。 求幾個數最大公因數的方法,開始時用觀察比較的方法,即:先把每個數的因數找出來,然後再找出公因數,最後在公因數中找出最大公因數。 例如:求12與18的最大公因數。 12的因數有:1、2、3、4、6、12。 18的因數有:1、2、3、6、9、18。 12與18的公因數有:1、2、3、6。 12與18的最大公因數是6。 這種方法對求兩個以上數的最大公因數,特別是數目較大的數,顯然是不方便的。於是又採用了給每個數分別分解質因數的方法。 12=2×2×3 18=2×3×3 12與18都可以分成幾種形式不同的乘積,但分成質因數連乘積就只有以上一種,而且不能再分解了。所分出的質因數無疑都能整除程式分析:對n進行分解質因數,應先找到一個最小的質數k,然後按下述步驟完成:
(1)如果這個質數恰等於n,則說明分解質因數的過程已經結束,打印出即可。
(2)如果n<>k,但n能被k整除,則應打印出k的值,並用n除以k的商,作為新的正整數你n,
重複執行第一步。
(3)如果n不能被k整除,則用k+1作為k的值,重複執行第一步。
01 |
#include "stdio.h" |
02 |
#include "conio.h" |
03 |
main() |
04 |
{ |
05 |
int n,i; |
06 |
printf ( "\nplease input a number:\n" ); |
07 |
scanf ( "%d" ,&n); |
08 |
printf ( "%d=" ,n); |
09 |
for (i=2;i<=n;i++) |
10 |
while (n!=i) |
11 |
{ |
12 |
if (n%i==0) |
13 |
{ |
14 |
printf ( "%d*" ,i); |
15 |
n=n/i; |
16 |
} |
17 |
else |
18 |
break ; |
19 |
} |
20 |
printf ( "%d" ,n); |
21 |
getch(); |
22 |
} |
另一種形式:
01 |
//返回質因數陣列 |
02 |
Integer[] decPrime( int n) { |
03 |
List<Integer> list = new ArrayList<Integer>(); |
04 |
for ( int i=2;i
<= n;i++){ |
05 |
while (n != i){ |
06 |
if (n%i != 0){ |
07 |
break ; //不能整除肯定不是因數,能夠整除在這裡一定是質數。因為所有的2,3,5,7 |
08 |
//都被除完之後。剩下的因數只能是奇數,且是質數。 |
09 |
} |
10 |
list.add(Integer.valueOf(i)); |
11 |
n = n/i; |
12 |
} |
13 |
} |
14 |
list.add(Integer.valueOf(n)); |
15 |
return list.toArray( new Integer[list.size()]); |
16 |
} |
另外程式碼:
。我們用所有正整數試驗一下,從2開始進行試除,逐步增加除數的值,去尋找一個可以整除n的數。在Eratosthenes篩法的討論中,我們知道如果n是一個複合數,那麼它就會有一個素數 。演算法9.3所示的就是這種方法的虛擬碼。這個演算法有兩個偱環路徑,外部的和內部的。外部迴圈求唯一因數,內部迴圈求一個因數的多個複本。例如, ,外部迴圈求出因數2和3。內部迴圈求出2是一個多因數。
01 |
void trial_divisio_fac( int n) |
02 |
{ |
03 |
int a=2; |
04 |
while (a*a<=n) |
05 |
{ |
06 |
while (n%a==0) |
07 |
{ |
08 |
cout<<a<<ends; |
09 |
n=n/a; |
10 |
} |
11 |
a++; |
12 |
} |
13 |
if (n>1) cout<<n; //n沒有因數 |
14 |
} |
上面的程式碼解釋比較清楚。為什麼這種方法可以得到素數。
因為我們在內層迴圈中,已經把當前a的所有倍數都去除了。這跟埃斯托尼演算法是一樣的。
複雜度 如果 ,這種情況下試除法通常都是很有效的。但是如果用來分解更大的整數,試除法就變得非常低效甚至不可用了。這種演算法的複雜度是隨著n的增加呈指數級別增長的。
(
試除法是整數分解演算法中最簡單和最容易理解的演算法。
給定一個合數n(這裡,n是待分解的整數),試除法看成是用小於等於的每個素數去試除待分解的整數。如果找到一個數能夠整除除盡,這個數就是待分解整數的因子。
).
例9.29
運用試除演算法求1233的因數。
1233=3^2*137.
轉自:http://www.cnblogs.com/youxin/p/3232049.html