最近在学树状数组,于是乎找了几个树状数组模板题练一下手;
题意:给你数字n,找出从零到n中,有多少孪生素数;
孪生素数是指两个连续的素数的差值为2;
例如(3, 5),(5,7)等;
Sample Input
1 5 20 -2
Sample Output
0 1 4
刚开始看这道题的时候,第一反应直接暴力,方正数据范围也不是很大;
第一发代码,无丝毫优化,毫无疑问直接给跪了;
#include<stdio.h>
#include<string.h>
int prim[10000],t;
void init()
{
bool is[100005];
t=0;
memset(is,false,sizeof(is));
prim[t++] = 1;
for(int i=2; i<100000; i++)
if(is[i] == false)
{
prim[t++] = i;
for(int j=i*2; j<100000; j +=i)
is[j] = true;
}
}
int main()
{
int n;
init();
while(scanf("%d",&n),n>=0)
{
int s=0;
for(int i=1; prim[i]<=n; i++)
if(prim[i]-prim[i-1]==2) s++;
printf("%d\n",s);
}
return 0;
}
于是乎优化了一下,直接AC;
#include<stdio.h>
#include<string.h>
int prim[10000],s[100005],t;
void init()
{
bool is[100005];
t=0;
memset(is,false,sizeof(is));
memset(s,0,sizeof(s));
prim[t++] = 1;
for(int i=2; i<100000; i++)
if(is[i] == false)
{
prim[t++] = i;
for(int j=i*2; j<100000; j +=i)
is[j] = true;
}
int a=1;
for(int i=2; i<100000; i++)
if(i == prim[a])
{
if(prim[a]-prim[a-1]==2)
s[i] = s[i-1]+1;
else s[i] = s[i-1];
a++;
}
else s[i] = s[i-1];
}
int main()
{
int n;
init();
while(scanf("%d",&n),n>=0)
{
printf("%d\n",s[n]);
}
return 0;
}
然后有敲了一发树状数组;
#include<stdio.h>
#include<string.h>
int prim[10000],s[100005],t;
void add(int n,int x)
{
while(n<100000)
{
s[n] += x;
n += n&-n;
}
}
int sum(int n)
{
int m=0;
while(n>0)
{
m += s[n];
n -= n&-n;
}
return m;
}
void init()
{
bool is[100005];
t=0;
memset(is,false,sizeof(is));
prim[t++] = 1;
for(int i=2; i<100000; i++)
if(is[i] == false)
{
prim[t++] = i;
for(int j=i*2; j<100000; j +=i)
is[j] = true;
}
memset(s,0,sizeof(s));
for(int i=1; i<t; i++)
if(prim[i]-prim[i-1]==2)
add(prim[i],1);
}
int main()
{
int n;
init();
while(scanf("%d",&n),n>=0)
printf("%d\n",sum(n));
return 0;
}