3. 在這裡我們來看看如何修改本問題,
而同時求出2到n之間每一個數的因數分解,
這是Dexter Kozen提出來的方法。
因為每個合成數r都可以寫成p^i * q的形式,
p為r最小的質因數。
當要刪除r時,我們在程式中就會知道p、i、q的值,
我們可以準備三個陣列來存P[r]、EXP[r]、Q[r]。
只要先將P[]初始化成0,在程式執行完後,
P[r]=0的r肯定是質數,其他的狀況則為合成數。
那我們知道r^i次方的部分,接著再往下找P[Q[r]],
一路找下去就可以將r給分解完成。
個人解答:
我們將輸出的格式定為如下:
60 = 2(2)3(1)5 (括號內的數為次方項)
在這種狀況下,我們為了要求每一個數的因數分解,
那麼就沒辦法無視2的倍數了。
所以前面只用next方法依舊是可以用,
但初始化時要改為每次+1,且LEFT(x) 改為x-1。
這裡就直接使用最原本的線性篩法來解答。
在三重迴圈中,除了相應的陣列外,
我們多加了一個pcnt,每次從新的q開始時就要重置,
而在第三層迴圈是每次乘上pcnt,自然要進行遞增。
當我們要進行刪去時,
有兩種情況:
1. prime == q
這種情況下p^pcnt*q相當於p^(pcnt+1),
因此給值P[mult]=prime,EXP[mult]=pcnt+1,Q[mult]=1
2. prime < q
給值P[mult]=prime,EXP[mult]=pcnt,Q[mult]=q
然後在讀取每一個數的時候,分下列三種狀況:
1. P[i] == 0
主程式中由於我們會先用迴圈對陣列初始化為0,
因此當碰到0的狀況時,表示它已經是質數了,
因此就輸出這個數本身即可。
2. Q[i] == 1
這個狀況代表說這個數為p的EXP[mult],
那麼只要輸出P[mult](EXP[mult])即可。
3. else
除此以外的狀況,表示在將p^i的部分表示出來以後,
q還可以被分解,那麼就用遞迴的方式,
將Q[mult]做為參數傳遞進去,最後就可以完全分解。
Code:
void L_Sieve(unsigned long n,unsigned long *P,unsigned long *Q,unsigned long *EXP) { unsigned long prev[MAXSIZE+1], next[MAXSIZE+1]; unsigned long prime, q, i, mult, cnt = 0; unsigned long pcnt; INITIAL(n); for(prime=2; prime*prime <= n; NEXT(prime)) for(q=prime, pcnt=1; prime*q <= n; NEXT(q), pcnt=1) for(mult=prime*q; mult <= n; mult*=prime, pcnt++) { if(prime==q){ P[mult] = prime; EXP[mult] = pcnt+1; Q[mult] = 1; } else{ P[mult] = prime; EXP[mult] = pcnt; Q[mult] = q; } REMOVE(mult); } for(i = 2; i!= NULL; NEXT(i)) { if(cnt % 8 == 0) printf("\n"); printf("%6ld", i); cnt++; } printf("\n\nTotal Prime Count: %ld \n", cnt); } void factor(unsigned long i, unsigned long *P, unsigned long *Q, unsigned long *EXP){ if(P[i]==0) printf("%ld", i); else if(Q[i] == 1){ printf("%ld(%ld)", P[i], EXP[i]); } else{ printf("%ld(%ld)", P[i], EXP[i]); factor(Q[i],P,Q,EXP); } } int main(int argc, char *argv[]) { // Initializing. unsigned long P[MAXSIZE+1], EXP[MAXSIZE+1], Q[MAXSIZE+1]; unsigned long i; for(i=2;i<=MAXSIZE+1;i++){ P[i]=EXP[i]=Q[i]=0; } L_Sieve(MAXSIZE,P,Q,EXP); for(i=2;i<=MAXSIZE;i++){ printf("%ld = ",i); factor(i,P,Q,EXP); printf("\n"); } system("PAUSE"); return 0; }
沒有留言:
張貼留言