问题:求小于等于n的素数个数
一般方法:从1~n都使用for循环判断是否为素数,时间复杂度为O(n2),纵然优化后,在每一个for循环中取n=sqrt(n)判断,仍然会是O(3/2)的复杂度。为了将算法优化到线性级别,考虑使用辅助数组。
思路如下:设置2~n的for循环,定义check数组,初始值为0。遍历过程中,若某数为i的整倍数(如4为2的两倍,6为2的3倍),则设置check标记值为1,表示非素数。(普通筛选法--埃拉托斯特尼筛法)
优化:在埃氏筛法中,会有数字被重复标记。此处引入欧拉算法。
参考:http://www.cnblogs.com/grubbyskyer/p/3852421.html
#include<cstdio>
#include<cstring>
#include <iostream>
using namespace std;
#define MAXN 100005
#define MAXL 1299710
int prime[MAXN];
int check[MAXL];
int main()
{
int tot = 0;
memset(check, 0, sizeof(check));
for (int i = 2; i < MAXL; ++i)
{
if (!check[i])
{
prime[tot++] = i;
}
for (int j = 0; j < tot; ++j)
{
if (i * prime[j] > MAXL)
{
break;
}
check[i*prime[j]] = 1;
if (i % prime[j] == 0)
{
break;
}
}
}
int n;
while(cin>>n)
{
int start=0;
int number=0;
while(prime[start]<=n)
{
//cout<<"test"<<prime[start]<<endl;
start++;
number++;
}
cout<<number<<endl;
}
}
欧拉函数: 在数论,对正整数n,欧拉函数是小于或等于n的数中与n互质的数的数目。例如φ(8)=4,因为1,3,5,7均和8互质。
仍然参考上述链接中的代码:
1 #include<cstdio>
2 #include<cstring>
3 #define MAXN 100005
4 #define MAXL 1299710
5 int prime[MAXN];
6 int check[MAXL];
7 int phi[MAXL];
8 int tot = 0;
9 phi[1] = 1;
10 memset(check, 0, sizeof(check));
11 for (int i = 2; i < MAXL; ++i)
12 {
13 if (!check[i])
14 {
15 prime[tot++] = i;
16 phi[i] = i - 1;
17 }
18 for (int j = 0; j < tot; ++j)
19 {
20 if (i * prime[j] > MAXL)
21 {
22 break;
23 }
24 check[i*prime[j]] = 1;
25 if (i % prime[j] == 0)
26 {
27 phi[i*prime[j]] = phi[i] * prime[j];
28 break;
29 }else
30 {
31 phi[i*prime[j]] = phi[i] * (prime[j]-1);
32 }
33 }
34 }