数论:素数判定
-
素數(shù)判定
所謂素數(shù): 指恰好有2個約數(shù)的整數(shù)。
判定: 因為n的約數(shù)都不超過n, 所以只要檢查 2 ~ n-1 的所有整數(shù)是否整除n就能判定n是不是素數(shù)。
在此,如果d 是 n的約數(shù), 那么 n/d也是n的約數(shù)。由n = d * n / d 可知 min(d, n/d) <= 根號n? , 所以只要檢查 2 ~ ? 根號n 的所有整數(shù)就足夠了。
同理可知,整數(shù)分解和約數(shù)枚舉都可以在 O(根號n?) 時間完成。(還有更高效的算法)
#include <iostream> #include <map> #include <vector> using namespace std; ? //假設(shè)輸入的都是正數(shù) //素性測試 bool is_prime(int n) {for (int i = 2; i * i <= n; i++) {if (n % i == 0) return false;}return n != 1; //1是例外 } ? //約數(shù)枚舉 vector<int> divisor(int n) {vector<int> res;for (int i = 1; i * i <= n; i++) {if (n % i == 0) {res.push_back(i);if (i != n / i) {res.push_back(n / i);}}}return res; } ? //整數(shù)分解 map<int, int> prime_factor(int n) {map<int, int> res;for (int i = 2; i * i <= n; i++){while (n % i == 0) {++res[i];n /= i;}}if (n != 1) {res[n] = 1;} ?return res; } ? int main() {//記住這個就差不多了cout << "素性測試: " << is_prime(7) << endl;cout << "==================================================\n";cout << "約數(shù)枚舉(約數(shù)總數(shù)為2,則為素數(shù)):\n";vector<int> res = divisor(13); // for (const auto& e : res) { // cout << e << " "; // } cout << (res.size() == 2) << endl;cout << "==================================================\n";cout << "整數(shù)分解(他沒有被任何數(shù)分解:\n";int n = 19;map<int, int> res2 = prime_factor(n); // for (auto it = res2.begin(); it != res2.end(); ++it) // { // cout << it->first << " " << it->second << " "; // cout << endl; // }cout << (res2[n] == 1) << endl; ?return 0; }
-
誒氏篩法
如果只對一個整數(shù)進行素性測試, 通常 ? 的算法就夠了,如果要對許多整數(shù)進行素性測試,則有更高效的算法。
素數(shù)的個數(shù)
給定整數(shù)n, 請問n以內(nèi)有多少個素數(shù)?
限制條件:
?n <= 10^6
#include <iostream> using namespace std; ? const int maxn = 10000000; int prime[maxn]; //第i個素數(shù) bool is_prime[maxn + 1]; //is_prime[i]為true 表示i是素數(shù) ? //返回n以內(nèi)的素數(shù)個數(shù) int sieve(int n) {int p = 0; //統(tǒng)計素數(shù)的個數(shù)//初始化for (int i = 0; i <= n; i++) {is_prime[i] = true;}is_prime[0] = is_prime[1] = false; ?for (int i = 0; i <= n; i++) {if (is_prime[i]) {prime[p++] = i; //將素數(shù)添加到prime中//1.首先2是素數(shù), 然后劃去所有2的倍數(shù)//2.表中剩余的最小數(shù)字是3, 它不能被更小的數(shù)整除, 所以是素數(shù)。再將表中所有3的倍數(shù)都劃去//3.依次類推, 如果表中剩余的最小數(shù)字是m時, m就是素數(shù)。然后將表中所有m的倍數(shù)都劃去。像這樣,就能依次枚舉n以內(nèi)的素數(shù)。for (int j = 2 * i; j <= n; j += i) {is_prime[j] = false;}}}return p; } ? int main() { ?int cnt = sieve(30);for (int i = 0; i < cnt; i++) {cout << prime[i] << " ";}cout << endl;return 0; }
-
用埃氏素數(shù)解決藍橋杯簡單題
第八屆藍橋杯第二題:
標題:等差素數(shù)列
?
2,3,5,7,11,13,....是素數(shù)序列。
類似:7,37,67,97,127,157 這樣完全由素數(shù)組成的等差數(shù)列,叫等差素數(shù)數(shù)列。
上邊的數(shù)列公差為30,長度為6。
?
2004年,格林與華人陶哲軒合作證明了:存在任意長度的素數(shù)等差數(shù)列。
這是數(shù)論領(lǐng)域一項驚人的成果!
?
有這一理論為基礎(chǔ),請你借助手中的計算機,滿懷信心地搜索:
?
長度為10的等差素數(shù)列,其公差最小值是多少?
?
注意:需要提交的是一個整數(shù),不要填寫任何多余的內(nèi)容和說明文字。
#include <iostream>
using namespace std;
?
const int maxn = 10000000;
int prime[maxn]; //第i個素數(shù)
bool is_prime[maxn + 1]; //is_prime[i]為true 表示i是素數(shù)
?
int sieve(int n);
bool isPrime(int n);
void solve();
?
//返回n以內(nèi)的素數(shù)個數(shù)
int sieve(int n)
{int p = 0; //統(tǒng)計素數(shù)的個數(shù)//初始化for (int i = 0; i <= n; i++) {is_prime[i] = true;}is_prime[0] = is_prime[1] = false;
?for (int i = 0; i <= n; i++) {if (is_prime[i]) {prime[p++] = i; //將素數(shù)添加到prime中//1.首先2是素數(shù), 然后劃去所有2的倍數(shù)//2.表中剩余的最小數(shù)字是3, 它不能被更小的數(shù)整除, 所以是素數(shù)。再將表中所有3的倍數(shù)都劃去//3.依次類推, 如果表中剩余的最小數(shù)字是m時, m就是素數(shù)。然后將表中所有m的倍數(shù)都劃去。像這樣,就能依次枚舉n以內(nèi)的素數(shù)。for (int j = 2 * i; j <= n; j += i) {is_prime[j] = false;}}}return p;
}
?
//素性測試
bool isPrime(int n)
{for (int i = 2; i * i <= n; i++) {if (n % i == 0) return false;}return n != 1; //1是例外
}
?
void solve()
{int N = 10000;int cnt = sieve(N);
// cout << cnt << endl;for (int i = 1; i <= N; i++) //枚舉 1~1000的公差
{for (int j = 0; j < cnt; j++) {int flag = 1, //標志 tmp = prime[j]; //第j個素數(shù)for (int k = 1; k < 10; k++) //第一個數(shù)已經(jīng)確定是素數(shù)
{if (tmp + i > N || !isPrime(tmp + i)) {flag = 0; break;}else {tmp = tmp + i; //下一個數(shù)
}}//如果 連續(xù)9個公差為i的數(shù)都是素數(shù) if (flag) {cout << i << " 開始的素數(shù):" << prime[j] << endl;return;}}}
}
?
int main()
{solve();return 0;
} -
練習(xí)題
POJ 3126: Prime Path
POJ 3421: X-factor Chains
POJ 3292: Semi-prime HB-numbers
?
轉(zhuǎn)載于:https://www.cnblogs.com/douzujun/p/7955764.html
總結(jié)
- 上一篇: 洱海上午去还是下午去好
- 下一篇: 1035等差数列末项计算