素數即質數,指在大於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的所有因子...