1.枚举法
当n比较小时,使用暴力枚举法是可行的,即如果要判断n是否是素数,则令i=2,判断n是否能整除i,直到<=根号n(在此,如果 d 是 n 的约数,那 n/d 也是 n 的约数,则由n=d*n/d 可知 min(d,n/d) <=根号n ,所以只要到根号n就可以, 不必到n-1 )
code:
bool is_prime(int n)
{
for(int i = 2; i*i<=n ; i++)
{
if(n%i==0)
return false;
}
return n!=1; //1是例外
}
2.打表法(埃氏筛法)
当n比较大,那用枚举法就不太合适了。或者,要求n范围内有多少素数,都可以用此方法来实现。
First of all , 2->n 中最小的素数是2,将表中所有的素数都划掉。剩余最小素数是3,再将3所有的倍数都划掉。依此类推,便能枚举n内所有的素数。
code:
int prime[max_N]; //函数里的p是最大下标,即为素数个数, 并可表示第i个素数是多少
int is_prime[max_N+1]; //1为素数,0则不是
int sieve(int n)
{
int p=0; //初始化素数个数为0
for(int i=2;i<=n;i++) is_prime[i]=1; //初始化所有数均为素数
is_prime[1]=is_prime[0]=0;
for(int i=2;i<=n;i++)
{
if( is_prime[i] )
{
prime[p++]=i; //i是素数
for(int j=i+i;j<=n;j+=i){
is_prime[j]=0; //i的倍数都不是素数 ,所以赋0
}
}
}
return p; //返回的p是n以内的素数个数
}
**注:**如果区间不是n以内即0->n ,是 [a,b)内的素数个数的话,也可用此方法求,不过,需先求得 [2,根号b )内的素数表,再筛选 [2,根号b ) 中素数的个数时,同时筛选其倍数 在[a,b) 并将其划去 ,最后即可剩下 [a,b)中素数的个数。
附:HDU 1215-七夕节
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1215
题意:求n以内所有n的因子和
code:
#include <cstdio>
#include <cstring>
#define Max 500002
int a[Max];
void panter()
{
int i,j;
memset(a,0,sizeof(0));
for(i=1;i<Max;i++) //从1开始,因为每个数都有1这个因子
{
for(j=2*i;j<Max;j+=i)
{
a[j]+=i; //依次加上倍数链的因子
}
}
}
int main()
{
int T,n;
panter();
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%d\n",a[n]);
}
return 0;
}