hdu3792 Twin Prime Conjecture
本题的大致题意为在n的范围内,找有几对孪生素数。例如样例输入输出那样,输入为5时,只能找到3和5两个相差2的孪生素数,即孪生素数的定义为(p,p+2),其中p和p+2都要为素数。
接下来贴一下素数筛法的代码
// 1:这是最原始的筛法,还有待优化
#define Max 1000000
bool prime[Max];
void IsPrime(){
prime[0]=prime[1]=0;prime[2]=1;
for(int i=3;i<max;i++)
prime[i]=i%2==0?0:1;
int t=(int)sqrt(Max*1.0);
for(int i=3;i<=t;i++)
if(prime[i])
for(int j=i;j<Max;j+=i)
prime[j]=0;
}
//2:优化后的筛法,手动地模拟原始筛法就可以发现,某个数字可能被不止一次地删去
// 优化后的筛法就可以避免这种不必要的删去操作
#define Max 1000000
bool prime[Max];
void IsPrime(){
prime[0]=prime[1]=0;prime[2]=1;
for(int i=3;i<max;i++)
prime[i]=i%2==0?0:1;
int t=(int)sqrt(Max*1.0);
for(int i=3;i<=t;i++)
if(prime[i])
for(int j=i*i;j<Max;j+=2*i)//优化
prime[j]=0;
}
树状数组:基本与线段树一样,都具有查询sum(),和更新update()的功能,树状数组代码量相比线段树会更短更好理解,但是他有局限性,一般树状数组能做的题目,线段树也能做,树状数组只能对一个数进行更新,而不能对一个区间进行,更新,这就是他的局限性。 下面贴下本题代码
#include<stdio.h>
#include<string.h>
#define MAX 100000
int c[100000];//以下三个接口为线段树的基本模版
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int num)
{
while(x<=MAX)
{
c[x]+=num;
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=0;
while(x>0)
{
ans+=c[x];
x-=lowbit(x);//把n的二进制的最后一个1减去
}
return ans;
}
int flag[100000],p[10000];//flag为素数筛法准备。
int main()
{
int i,j,tot=0;
memset(flag,0,sizeof(flag));
for(i=2;i<=100000;i++)
{
if(!flag[i])
{
p[++tot]=i;
for(j=2*i;j<=100000;j+=i)
{
flag[j]=1;
}
}
}
for(i=2;i<=tot;i++)
{
if(p[i]-p[i-1]==2)
{
add(p[i],1);//p[i]+1
}
}
int n;
while(scanf("%d",&n),n>0)
{
if(n==0) printf("0\n");
else
printf("%d\n",sum(n));//查询
}
return 0;
}
下面是Stars的链接和代码,其大致的意思,为输入n个星星的横坐标和纵坐标,不难发现纵坐标的输入为从小到大,每个星星都有自己的level,level为横纵坐标不大于它的星星个数,本题依然用到树状数组。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int N;
const int maxn = 32005;
int c[maxn]; //树状数组
int level[maxn];
int Lowbit(int x)
{
return x & (-x);
}
int sum(int end)
{
int sum = 0;
while(end>0)
{
sum += c[end];
end -= Lowbit(end);
}
return sum;
}
void update(int pos)
{
while(pos<=32001)
{
c[pos] ++;
pos += Lowbit(pos);
}
}
int main()
{
int m,i,a,b;
while(cin>>m)
{
memset(c,0,sizeof(c));
memset(level,0,sizeof(level));
for(i=1; i<=m; i++)
{
scanf("%d%d",&a,&b);
level[sum(a+1)]++;
update(a+1);
}
for(i=0; i<m; i++)
{
cout<<level[i]<<endl;
}
}
}