最近在學樹狀數組,於是乎找了幾個樹狀數組模板題練一下手;
題意:給你數字n,找出從零到n中,有多少孿生素數;
孿生素數是指兩個連續的素數的差值爲2;
例如(3, 5),(5,7)等;
剛開始看這道題的時候,第一反應直接暴力,方正數據範圍也不是很大;
第一發代碼,無絲毫優化,毫無疑問直接給跪了;
#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;
}