素數表 因式分解 完美數

2021-06-19 17:44:40 字數 3465 閱讀 1578

素數即質數,指在大於1的自然數中,除了1和此整數自身外無法被其它自然數整除的數。

該方法用於驗證乙個數是否為素數。例求x是否為素數,只需要驗證1到中是否存在乙個數字x的約數,即能被x整除。

該方法用於高效的求出小於任何數n的所有素數。該方法的原理為先用乙個篩子存放所有的數,顯然其中最小的為2且為質數,這時可以過濾掉2的任何倍數。緊接著尋找比2大的最小數3,則過濾掉所有3的倍數。如此,比已經找到的質數大的最小數即為素數,然後刪除該素數的所有倍數。最終將篩選出所有小於n的素數。

void test()

int prime[primemax + 1];

for (int i = 2; i < primemax; i++)

prime[i] = 1;

for (int i = 2; i * i <= primemax; i++)

if (1 == prime[i])

for (int j = 2 * i; j <=primemax; j++)

if (0 == j % i)

prime[j] = 0;

for (int i = 2; i < primemax; i++)

if (1 == prime[i])

coutcout<

這裡的因式分解是指將乙個數分解成若干個素數乘積的形式。例如12 = 2 * 2 * 3。算數基本定理證明每個大於1的正整數都可以寫成素數的乘積,並且這種乘積的形式是唯一的。因此素數也被稱為自然數的「建築的基石」。可以用以下方法分解n。

讓n去除從1到的任意數,直到商為1則所有的能被整除的數即為n的一項,若某個數能被整除m次,則n的因式中應該還有m個該數。

例如n=12,則:

n=12能整除2,得6……n的乙個因子為2

n=6能整除2,得3……n的乙個因子為2

n=3能整除3,得1……n的乙個因子為3

因為商為1,則停止運算可得n=12=2*2*3為n的因式分解。

試除法存在的問題為不是所有的被除數都為素數,例如n=30,當整除2和3後,又去試除4,顯然這是沒有必要的。因此可以預處理一張素數表,繼2和3之後去試除5而不再是4。

#define maxnum110000

int num1;

intprimetable[maxnum1];

void prime()

int temp[maxnum1];

int genprime = 0;

for (int i = 0; i < maxnum1; i++)

temp[i] = 1;

primetable[i] = 1;

for (int i = 2; i < maxnum1; i++)

if (1 == temp[i])

primetable[genprime++] = i;

for (int j = 2*i; j if (0 == j % i)

temp[j] = 0;

void factor()

int num = num1;

coutif (0 == num % primetable[i])

coutelse

++i;

coutprime();

factor();

如果乙個數n,其真約數(比n小的約數)的總和等於n,則稱之為完美數。例如6 = 1 + 2 + 3,28 = 1 + 2 + 4 + 7 + 14。

求出數n的所有真約數,然後相加判斷是否與n相等即可,若相等則是完美數,反之不是。

由算數基本定理可得任何數n均可分解為若干素數的乘積,而乙個數的所有約束應該為所有這些約數的組合和1。例如n=12=2*2*3的分解素數為2、2以及3,他們的組合數為2、4、6、12,顯然與1一起組成了n=12的所有約束。若n為完美數則有n分解的素數的所有組合數的和加上1為n的2倍。例如:

2 * 28 = 1 + 2 + 4 + 7 + 14 + 28 = (20 + 21 + 22)*(70 + 71)

顯然等式的右邊為用n=28的分解成的素數組成,即若某乙個素數x有m個,則組合數中可以包含0、1……m個,對約數的貢獻分別為x0, x1……xm。

完美數的求解總共分為三步:

(1) 求出一定數目的素數表

(2) 利用素數表求指定數的因式分解

(3) 利用因式分解求所有真約數和,並判斷是否為完美數

#define n 1000

#define p 10000

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;

int factor(int*table, int num, int* frecord)

int i, k;

for(i = 0, k = 0; table[i] * table[i]<= num;)

if(num % table[i] == 0)

frecord[k] = table[i];

k++;

num /= table[i];

else

i++;

frecord[k] = num;

return k+1;

int fsum(int*farr, int c)

int i, r, s, q;

i = 0;

r = 1;

s = 1;

q = 1;

while(i < c)

do r *= farr[i];

q += r;

i++;

} while(i < c-1 &&farr[i-1] == farr[i]);

s *= q;

r = 1;

q = 1;

return s / 2;

int main(void)

int ptable[n+1] = ; // 儲存質數表

int fact[n+1] = ;     // 儲存因式分解結果

int count1, count2, i;

count1 = prime(ptable);

for(i = 0; i <= p; i++)

count2 = factor(ptable, i, fact);

if(i == fsum(fact, count2))

printf("perfect number:%d\n", i);

printf("\n");

return 0;

因式分解與完美數

1.1怎樣因式分解?求出小於該數的所有質數,看是不是可以被該數整除,從而完成因式分解。ps 再求n的所有質數時用sqrt 函式,只需要迴圈嘗試 sqrt n 的數就行,減少迴圈次數 另外,每找到乙個因子i,要把n變成n i,以保證繼續找下乙個因子,正確分解。2.1.何為完美數?如果有一數n,其真因數...

階乘因式分解

時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述 給定兩個數n,m,其中m是乙個素數。將n 0 n 2 31 的階乘分解質因數,求其中有多少個m。注 為求冪符號。輸入 第一行是乙個整數s 0 輸出輸出m的個數 樣例輸入 3 100 5 16 2 1000000000 13 樣例...

因式分解總結

因式分解其實是乙個很簡單的應用,這裡做一下小小的總結 計算乙個數的所有因子 這裡只需要找到這個數的平方根的因子,然後再用該數分別除以每個因子,就會找到每個因子對應的另乙個因子 int a 10000 num 0 儲存n的因子 void factor int n a中從0到num 1儲存了n的所有因子...