判質數
質數概念:在大於1的整數中,如果只包含1和本身這兩個約數,就被稱爲質數或者叫素數。
質數性質:如果d/n能整除,那麼n/d / n也能整除。
比如n = 12, 3和4都是他的約數,n的約數都是成對出現的 。在枚舉的時候我們可以只枚舉沒對較小的一個就可以了。
給定n個正整數aiai,判定每個數是否是質數。
輸入格式
第一行包含整數n。
接下來n行,每行包含一個正整數aiai。
輸出格式
共n行,其中第 i 行輸出第 i 個正整數aiai是否爲質數,是則輸出“Yes”,否則輸出“No”。
數據範圍
1≤n≤1001≤n≤100,
1≤ai≤2∗1091≤ai≤2∗109
輸入樣例:
2
2
6
輸出樣例:
Yes
No
#include <iostream>
using namespace std;
bool is_prime(int x)
{
if(x < 2) return false;
for (int i = 2; i <= x / i; i ++)
if (x % i == 0) return false;
return true;
}
int main()
{
int n;
cin >> n;
while(n --)
{
int x;
cin >> x;
if(is_prime(x)) puts("Yes");
else puts("No");
}
}
分解質因數
概念:從小到大枚舉所有的數。
給定n個正整數aiai,將每個數分解質因數,並按照質因數從小到大的順序輸出每個質因數的底數和指數。
輸入格式
第一行包含整數n。
接下來n行,每行包含一個正整數aiai。
輸出格式
對於每個正整數aiai,按照從小到大的順序輸出其分解質因數後,每個質因數的底數和指數,每個底數和指數佔一行。
每個正整數的質因數全部輸出完畢後,輸出一個空行。
數據範圍
1≤n≤1001≤n≤100,
1≤ai≤2∗1091≤ai≤2∗109
輸入樣例:
2
6
8
輸出樣例:
2 1
3 1
2 3
//步驟:求a能被i整除的最小的數i(從2開始遍歷),並且使用while循環用d來存底數,a/=i繼續往下除,直到除不下爲止。
// 輸出累除的結果i和d
#include <iostream>
using namespace std;
int n;
void divide(int a)
{
for (int i = 2; i <= a / i; i ++)//這裏是a/i
{
if (a % i == 0)
{
int d = 0;//存底數
while(a%i == 0)
{
d ++;
a/= i;
}
cout << i << " " << d << endl;//這裏是輸出i,d。注意i實際上是指數
}
}
//每個質因數的底數和指數,每個底數和指數佔一行
if (a > 1) cout << a << " " << 1 << endl;
puts("");
}
int main()
{
cin >> n;
while(n --)
{
int a;
cin >> a;
divide(a);
}
return 0;
}
篩質數
~n中質數有n/ln(n)個質數
按順序刪除每個數的倍數,最後剩下的就是質數。
給定一個正整數n,請你求出1~n中質數的個數。
輸入格式
共一行,包含整數n。
輸出格式
共一行,包含一個整數,表示1~n中質數的個數。
數據範圍
1≤n≤1061≤n≤106
輸入樣例:
8
輸出樣例:
4
//步驟:1、循環i = 2,i <= n,i ++;2、當前數沒有被篩過,則標記它是個質數;3、//將n的倍數刪除掉
#include<iostream>
using namespace std;
const int N = 1000010;
int prime[N], cnt;
bool st[N];//標誌他是否是質數
int n;
//樸素做法
// void get_primes(int n)
// {
// for (int i = 2; i <= n; i ++)//不需要n / i
// {
// //步驟要記住!!!!
// if (!st[i])prime[cnt ++ ] = n;//當前數沒有被篩過,則是個質數
// for (int j = i + i; j <= n; j +=i) //將n的倍數刪除掉
// st[j] = true;//標記爲true
// }
// }
//埃式篩法-O(nloglogn)
// void get_primes(int n) {
// for(int i = 2; i <= n; i++) {
// if(!st[i]){
// prime[cnt++] = i;
// //跟樸素不一樣的事吧這個for循環放到了這裏,而且循環是從j = i,j+=i來做
// for(int j = i; j <= n; j += i)
// st[j] = true;
// }
// }
// }
//線性篩法-O(n), n = 1e7的時候基本就比埃式篩法快一倍了
//算法核心:x僅會被其最小質因子篩去
void get_primes(int x) {
for(int i = 2; i <= x; i++) {
if(!st[i]) prime[cnt++] = i;//找到質數
for(int j = 0; prime[j] <= x / i; j++) {//從0開始找j倍數
//對於任意一個合數x,假設pj爲x最小質因子,當i<x/pj時,一定會被篩掉
st[prime[j]*i] = true;//倍數直接標記
if(i % prime[j] == 0) break;
/*
1.i%pj == 0, pj定爲i最小質因子,pj也定爲pj*i最小質因子
2.i%pj != 0, pj定小於i的所有質因子,所以pj也爲pj*i最小質因子
*/
}
}
}
int main()
{
cin >> n;
get_primes(n);
cout << cnt << endl;
return 0;
}
求約數
使用試除法求一個數的所有約數。
1、從小到大枚舉所有約數
2、只枚舉每一對約數較小的
3、如果i != n / i,才加進去
給定n個正整數ai,對於每個整數ai,請你按照從小到大的順序輸出它的所有約數。
輸入格式
第一行包含整數n。
接下來n行,每行包含一個整數aiai。
輸出格式
輸出共n行,其中第 i 行輸出第 i 個整數aiai的所有約數。
數據範圍
1≤n≤100,
2≤ai≤2∗10^9
輸入樣例:
2
6
8
輸出樣例:
1 2 3 6
1 2 4 8
//步驟:1、學會用vector容器,vector<int> a;2、如果是一個約數則存起來res.push_back(i);
//3、可能會出現n = i * i的情況兩個餘數相同的情況,所以需要判斷一下if (i != n / i) res.push_back(n / i);
//4最後將約數排個序sort(res.begin(), res.end());
#include <iostream>
#include <vector>//存一個數的所有約數
#include <algorithm>
using namespace std;
vector<int> get_divisors(int n)
{
vector<int> res;
for (int i = 1; i <= n / i; i ++)
if (n % i == 0)//如果是一個約數,則存起來
{
res.push_back(i);
if (i != n / i) res.push_back(n / i);//可能會出現n = i * i的情況兩個餘數相同的情況,所以需要判斷一下
}
//最後將約數排個序
sort(res.begin(), res.end());
return res;
}
int main()
{
int n;
cin >> n;
while(n --)
{
int x;
cin >> x;
auto res = get_divisors(x);//dedaox所有的約數
//循環遍歷所有約數
for(auto t : res) cout << t << ' ';
cout << endl;
}
return 0;
}