在开始的开始,推荐两个视频,额,我的入门视频(还没开始讲就让别人去别处的屑(bushi))
现在假如给我们一个题目,让你求出在
首先在最开始,先把我老是忘记的两个知识点写下来
满足了,老是忘...
首先最容易想到的是朴素的筛法
我们将
因为这个方法太过简单(bushi) 所以就不赘述了,具体的两个小细节放在代码里说
using namespace std;
typedef long long int lli;
vector<lli>info;
lli Limit;
bool origin(lli number){
lli Judge = sqrt(number) + 1;
//把这个数存下来避免重复运算,单一可以用i*i这种方式确定,因为sqrt运算慢
for(lli temp = 2 ; temp <= Judge ; temp++){
if(number % temp == 0) return 0;
}
return 1;
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> Limit;
info.push_back(2);
for(lli temp = 3 ; temp <= Limit ; temp += 2){//2的倍数肯定不是质数
if(origin(temp)) info.push_back(temp);
}
return 0;
}
嗯,大道至简,赏赐你一个TLE, 不用谢
下面我们就来介绍两种更加优化的筛法:埃式筛/欧拉筛
我们发现,一个合数一定是由某个素数相乘得来的
所以埃式筛法的核心便是:先求出一个素数,然后将素数的倍数标记下来 那么以后遍历到这个数就可以判断它不是素数了
给出一个简单的过程:
懒得搞下去了,相信不难懂
那么就到了愉快的代码时间
xxxxxxxxxx
using namespace std;
typedef long long int lli;
lli Limit;
vector<lli>info;
bitset<lli(1e8 + 10)> Check;
void Era_sieve(lli Limit){
for(lli temp = 2 ; temp <= Limit ; temp++){
if(Check[temp] == 0){
info.push_back(temp);
for(lli temp2 = temp*temp; temp2 <= Limit ; temp2 += temp)
Check[temp2] = 1;
}
}
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> Limit;
Era_sieve(Limit);
return 0;
}
首先要明白为啥欧拉算法要更优,在之前的表格中,有些数字被重复赋值
举个例子:我们把那张表格复制一份下来
不难发现,数字
所以我们尝试让这些数字只被遍历一次,这样就达到了线性的效果
对于一个合数来说,我们只需要让它被最小的质数质数筛掉就好了
所以我们将之前求得得=的数有小到大存起来,之后遍历这些素数,如果这个数可以被某一个质数整除,那么就结束这个循环
上代码
xxxxxxxxxx
using namespace std;
typedef long long int lli;
lli Limit;
vector<lli>info;
bitset<lli(1e8 + 10)> Check;
void Euler_sieve(lli Limit){
for(lli temp = 2 ; temp <= Limit ; temp++){
if(Check[temp] == 0) info.push_back(temp);
for(lli temp2 = 0 ; temp*info[temp2] <= Limit ; temp2++){
Check[temp*info[temp2]] = 1;
if(temp % info[temp2] == 0) break;
}
}
}
signed main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> Limit;
Euler_sieve(Limit);
return 0;
}
完结撒花
另外祝今晚CF顺利,还有不要怪我没写注释,我懒...