目录
当然肯定有更好的算法(更好背 :) )那就是埃拉托斯特尼筛法。简称埃氏筛法。
素数筛法简而言之就是将素数筛出的算法,将其他的数给筛掉。这篇博客就总结几个常见的算法模板。
朴素算法:判断一个数是否为素数?
作为大佬的你来说肯定不用解释,下面是代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
bool ispri(int x)
{
for(int i=2;i<=x;i++) if(x%i==0) return true;
return false;
}
int main()
{
int n;
if(ispri(n)) cout << "Yes";
else cout << "No";
return 0;
}
还有一个小小的优化:就是当一个数有一个因子的时候,那么一定有一个对应的因子。
像我这样的蒟蒻都明白,作为大佬的你来说轻轻松松。
所以我们就可以优化(其实不优化也可以),我们将搜索范围调小至2到根号n。
bool ispri(int x)
{
for(int i=2;i*i<=x;i++) if(x%i==0) return true;
return false;
}
damn是,这个算法就是逊啦,如果要求n以内的所有素数呢?
当然肯定有更好的算法(更好背 :) )那就是埃拉托斯特尼筛法。简称埃氏筛法。
核心思想:用一个数组is_prime,来记录i是否是素数——is_prime[i]==1表示不是素数。
同样我们只用筛至平方根处。
下面是代码:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e6+5;
vector<int> prime;
bool is_prime[N];
void Eratosthenes(int n)
{
for (int i = 2; i*i<= n; ++i) { //筛至平方根处
if (!is_prime[i]) {
prime.push_back(i);//i没有被筛掉,那么i为素数,将其放入prime数组
if (i * i > n) continue;//防止越界
for (int j = i * i; j <= n; j += i)
is_prime[j] = true;// 是 i 的倍数的均不是素数
// 因为从 2 到 i - 1 的倍数我们之前筛过了
// 这里直接从i的倍数开始,提高了运行速度
}
}
}
int main()
{
int x;
cin >> x;
Eratosthenes(x);
for(auto p : prime){
cout << p << ' ';
}
return 0;
}
聪明的你一定会发现如果i==2,那么就会筛到6,如果i==3,那么也会筛到6
怎么办馁?
那么还有一个算法就是欧拉筛。
核心思想:我们只让一个数的最小质因子去筛它,例如12的质因子有2,3我们就让2去筛。
所以我们仍然用一个数组记录质因子,当我们要尝试用j去筛数的时候,判断i是否为j的倍数,换而言之,j是否为i的最小质因子。如果不是,那么这个数就被筛过了,就返回。
下面是程序:
#include <bits/stdc++.h>
// #define IOS std::ios::sync_with_stdio(false), std::cin.tie(nuintptr)
using namespace std;
using ll = long long;
const int N = 1e6+5;
vector<int> prime;
bool is_prime[N];
void Eulersieve(int n)
{
for(int i=2;i<=n;++i){
if(!is_prime[i]){
prime.push_back(i);
}
for(int j : prime){
if(i*j>n) break;
is_prime[i*j] = true;
if(i % j == 0) break; //欧拉筛的优化核心
}
}
}
int main()
{
int x;
cin >> x;
Eulersieve(x);
for(auto p : prime){
cout << p << ' ';
}
return 0;
}
OK了,想必你一定看懂了。来写一道题吧:
很容易看出来,如果用暴力会超时,我们就可以考虑素数筛法。
思路:这道题目可以使用欧拉筛来做,我们预处理1e8以内的数的最小质因子,这样我们就可以短时间内处理,举个例子:一个数为60.
AC CODE:
#include <bits/stdc++.h>
// #define IOS std::ios::sync_with_stdio(false), std::cin.tie(nuintptr)
using namespace std;
using ll = long long;
const int N = 1e8+5;
int miny[N];
vector<int> pri;
bool not_prime[N];
void pre(int n)
{
for(int i=2;i<=n;++i){
if(!not_prime[i]){
pri.push_back(i);
miny[i] = i; //假设素数的最小质因子是它本身
}
for(int j : pri){
if(i*j>n) break;
not_prime[i*j] = true;
miny[i*j] = j; //i*j的最小质因子是j
if(i % j == 0) break;
}
}
}
int main()
{
int t;cin >> t;
pre(N-5);
while(t--){
int n;
cin >> n;
int ans = 0;
while(n!=1){
ans^=miny[n];
n/=miny[n];
}
cout << ans << endl;
}
}