質數、質因數個數和約數個數的求解
質數的判定
質數也稱素數,是指只能被其自身和1整數的正整數。
那麼如何判斷一個數是否為質數呢?可以用所有小於該數的正整數去試著除該數,若能整數,則不是質數;若這些數都不能整除它,則該數是質數。
要求
給定一個數n,要求判定是否為質數(0,1和負數都不是質數),若是則輸出yes,否則輸出no
程式碼
#include <cstdio> #include <cmath> using namespace std; /* * 判斷一個數是否是質數(素數) * */ bool Judge(int n){ if(n<2){ //小於2的數都不是質數 return false; } int bound = sqrt(n); // 程式碼優化,只需迴圈到根號n即可 for (int i = 2; i <= bound; ++i) { if (n % i == 0) { //如果能被整除則不是質數,返回false return false; } } return true; } int main(){ int n; while (scanf("%d",&n)!=EOF){ if(Judge(n)){ printf("yes\n"); } else { printf("no\n"); } } return 0; }
質數篩法
知道如何判定一個質數後,那麼如何找出0~100000之間的所有質數呢?依次列舉每個數,然後按照上文中的判斷方法確定其是否為質數。這樣做是可行的,但是時間複雜度太高了,這裡有一種更好的方法,那就是質數篩法。
找到一個質數,它的所有倍數均標記為非質數;這樣,當遍歷到一個數時,若它未被任何小於它的數標記為非質數,則確定其為質數
例如:
有這樣20個數(粗體為質數):
-
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 (初始全部為標記為質數)
-
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 (0,1為非質數排除)
-
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20(2是質數,它的所有倍數均為非質數)
-
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20(3是質數,它的所有倍數均為非質數)
這樣很快就算出來[0,20]之間的質數了
要求
輸出第k個質數(k<10000),如k=3時,輸出5
程式碼
// // Created by lxy on 2022/3/15. // #include <cstdio> #include <vector> using namespace std; const int MAXN = 1e5 + 10; vector<int> prime; //儲存質數 bool isPrime[MAXN]; //用來判斷該數是否為質數 /* * 質數篩法 * */ void Initial(){ fill(isPrime, isPrime + MAXN, true);// 先假設所有數是質數 isPrime[0] = false; // 0不是質數 isPrime[1] = false; // 1不是質數 for (int i = 2; i < MAXN; ++i) { if (!isPrime[i]) { // 不是質數就繼續 continue; } prime.push_back(i);//是質數就新增到向量中 if (i > MAXN / i) { // 等價於i*i>MAXN預防i*i越界int,提前判斷一下 continue; } for (int j = i*i; j < MAXN; j+=i) { //質數的倍數肯定是非質數 isPrime[j] = false; } } } int main(){ Initial(); int k; while (scanf("%d", &k) != EOF) { printf("%d\n", prime[k - 1]); } return 0; }
質因子分解
什麼是因子分解呢?
30=2 * 15
=5 * 6
=2 * 3 * 5 (所有因子都是質數時就稱質因子分解)
通常使用短除法來求質因子:一個數不斷的除以質數,直到等於1為止。例如:
120 / 2 = 60 (從第一個質數開始整除)
60 / 2 = 30
30 / 2 = 15
15 / 3 = 5 (此時2無法整除了,換下一個質數3)
5 / 5 = 1 (此時3也無法整除了,換下一個質數5)
所以\(120=2^3*3*5\)
\(對一個數x分解質因數就是確定質數p_1,p_2,···p_n,使其滿足x=p_1^{e_1}*p_2^{e_2}*···*p_n^{e_n}\)
要求
求正整數N(1<N<10^9)的質因子的個數,相同的質因子需要重複計算。例如120=2 * 2 * 2 * 3 * 5,有5個質因子
程式碼
#include <cstdio>
#include <vector>
using namespace std;
const int MAXN = 4e4;
vector<int> prime;
bool isPrime[MAXN];
/*
* 質數篩法
* */
void Initial(){
fill(isPrime, isPrime + MAXN, true);// 先假設所有數是質數
isPrime[0] = false;
isPrime[1] = false;
for (int i = 2; i < MAXN; ++i) {
if (!isPrime[i]) { // 不是質數就繼續
continue;
}
prime.push_back(i);//是質數就新增到向量中
if (i > MAXN / i) { // 預防i*i越界,提前判斷一下
continue;
}
for (int j = i*i; j < MAXN; j+=i) {
isPrime[j] = false;
}
}
}
/*
* 求質因子個數
* */
int NumberOfPrimeFactors(int number){
int answer = 0;
for (int i = 0; i < prime.size(); ++i) {
int factor = prime[i];
if (number < factor) {
break;
}
int exponent = 0; //記錄被除以的次數,即它的指數
while (number % factor == 0) { //不停的除以這個質數,直到不能整除為止
exponent++;
number /= factor;
}
answer += exponent;
}
if (number > 1) {// 還有一個大於根號number質因子
answer++;
}
return answer;
}
int main(){
Initial();
int number;
while (scanf("%d", &number) != EOF) {
printf("%d\n", NumberOfPrimeFactors(number));
}
return 0;
}
約數的個數
\[\begin{array}{c} 質因數分解 x=p_1^{e_1}*p_2^{e_2}*···*p_n^{e_n} \\ 數x約數的個數=(e_1+1)*(e_2+1)*···*(e_n+1) \end{array} \]120=2^3 * 3 * 5
120約數的個數有(3+1) * (1+1)*(1+1)= 16
程式碼
/*
* 求約數的個數
* */
#include <cstdio>
#include <vector>
using namespace std;
const int MAXN = 4e4;
vector<int> prime;
bool isPrime[MAXN];
/*
* 質數篩法
* */
void Initial(){
fill(isPrime, isPrime + MAXN, true);// 先假設所有數是質數
isPrime[0] = false;
isPrime[1] = false;
for (int i = 2; i < MAXN; ++i) {
if (!isPrime[i]) { // 不是質數就繼續
continue;
}
prime.push_back(i);//是質數就新增到向量中
if (i > MAXN / i) { // 預防i*i越界,提前判斷一下
continue;
}
for (int j = i*i; j < MAXN; j+=i) {
isPrime[j] = false;
}
}
}
/*
* 求約數個數
* */
int NumberOfFactors(int number){
int answer = 1;
for (int i = 0; i < prime.size(); ++i) {
int factor = prime[i];
if (number < factor) {
break;
}
int exponent = 0; //記錄被除以的次數,即它的指數
while (number % factor == 0) { //不停的除以這個質數,知道除不動
exponent++;
number /= factor;
}
answer *= exponent + 1;
}
if (number > 1) {
answer *= 2;
}
return answer;
}
int main(){
Initial();
int n;
scanf("%d",&n);
printf("%d\n", NumberOfFactors(n));
return 0;
}