prim[] 中值为0代表素数、1代表合数.
代码实现(复杂度为O(nloglogn)).
1: j = 2 * i;
prim [1] = 1;
for (int i =2; i *i < TOP ; i ++)
if (! prim [ i ])
for (int j = 2 * i;j < TOP ; j += i )
prim [ j ]=1;
2. j = i * i;
prim [1] = 1;
for (int i =2; i *i < TOP ; i ++)
if (! prim [ i ])
for (int j = i * i;j < TOP ; j += i )
prim [ j ]=1;
两者有什么区别呢?
来看这道题:
题目链接:PTA | 程序设计类实验辅助教学平台
1007 素数对猜想 (20 分)
作者: CHEN, Yue
单位: 浙江大学
时间限制: 200 ms
内存限制: 64 MB
代码长度限制: 16 KB
让我们定义dn为:dn=pn+1−pn,其中pi是第i个素数。显然有d1=1,且对于n>1有dn是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。
现给定任意正整数N
(<105),请计算不超过N
的满足猜想的素数对的个数。
输入格式:
输入在一行给出正整数N
。
输出格式:
在一行中输出不超过N
的满足猜想的素数对的个数。
输入样例:
20
输出样例:
4
题意:找小于等于N的素数中,相邻素数差为2的素数对有多少个.
我的第一个代码:
#include<iostream>
#include<cctype>
#include<vector>
#include<unordered_map>
#include<algorithm>
#include<math.h>
#include<string.h>
#define ll long long
using namespace std;
int prime[1000000];
int vis[1000000];
int main()
{
memset(vis, 0, sizeof vis);
int n;
cin>>n;
int cnt=0;
for(int i=2; i <= n; i++)
{
if(!vis[i])
{
prime[++cnt] = i;
// cout<<prime[cnt]<<' '<<cnt<<endl;
vis[i] = 1;
for(int j= i * i; j <= n; j=j+i)
vis[j] = 1;
}
}
// printf("1");
int ans=0;
for(ll i=2; i<=cnt; i++)
{
if(prime[i] - prime[i-1] == 2) ans++;
}
cout<<ans;
return 0;
}
不知道为什么段错误了,明明数组开的够大,数组下标也没有越界.
把 j = i * i 改为j= i * 2 后:
为什么?
原来,当 i * i的值大于int范围后,j的值会变成负数,负数做数组下标,当然re.
于是将代码中的int改成ll试了下.
总结: 两种筛法都可以,但要注意数据范围问题.