一道ACM练习题 提交一直cr 有高手做过的 指导下 怎样可以通过

oracleapple 2011-09-15 12:24:36
/*
Description

给定两个非负整数a,b,其中1<= a,b<=1,000,000,请计算这两个数之间有多少个素数。

输入

第一行是一个整数K(1<=K<=1000),表示有多少个样例,每个样例占一行,是两个整数a和b,
每个整数之间用一个空格隔开。

输出

每行输出一个样例的结果。

Sample Input

2
2 3
17 19


Sample Output

2
2

*/

#include<stdio.h>
#include<math.h>
int main(void)
{
int cases;
long a,b,i,j,c,count;
bool flag[2000000];
flag[0] = true;

for(i=1;i<2000000;i++)
{
if(i <= 3)
{
flag[i] = true;
continue;
}

if(0 == i % 2)
{
flag[i] = false;
continue;
}

c = (long)sqrtl((long double)i);

for(j=2;j<=c;j++)
{
if(0 == i % j)
{
flag[i] = false;
break;
}

if(c == j)
{
flag[i] = true;
break;
}
}
}
scanf("%d",&cases);

while(cases--)
{
count = 0;
scanf("%ld%ld",&a,&b);


for(i=a;i<=b;i++)
{
if(flag[i])
{
count++;
}
}

printf("%ld\n",count);

}


return 0;
}

...全文
97 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
oracleapple 2011-09-15
  • 打赏
  • 举报
回复
问题已解决 结贴给分
oracleapple 2011-09-15
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 oracleeason1 的回复:]

#include<stdio.h>
#include<math.h>
int main(void)
{
int cases;
long a,b,i,j,c,count;
bool flag[1010000];

//初始化这个标记数组 是素数标记为true 不是标记为false 主要用来降低时间复杂度
flag[0] = false;
flag[1] = false;
fo……
[/Quote]不愧是受过训练的```
oracleapple 2011-09-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 oracleeason1 的回复:]

1 不是素数
[/Quote]我擦```原来1不是素数```
  • 打赏
  • 举报
回复
1 不是素数
  • 打赏
  • 举报
回复
#include<stdio.h>
#include<math.h>
int main(void)
{
int cases;
long a,b,i,j,c,count;
bool flag[1010000];

//初始化这个标记数组 是素数标记为true 不是标记为false 主要用来降低时间复杂度
flag[0] = false;
flag[1] = false;
for(i=2;i<4;i++)
{
flag[i] = true;
}

for(i=4;i<1010000;)
{
flag[i] = false;
i += 2; //步长为2增加
}
for(i=5;i<1010000;)
{
c = (long)sqrtl((long double)i);

for(j=2;j<=c;j++)
{
if(0 == i % j)
{
flag[i] = false;
i += 2;
break;
}

if(c == j)
{
flag[i] = true;
i += 2;
break;
}
}
}

scanf("%d",&cases);//cases个测试用例

while(cases--)
{
count = 0;
scanf("%ld%ld",&a,&b);

//判断第一种情况
if(a <= 1 && b > 1)
{
a = 2;
}

//第二种
if(b <= 1 && a > 1)
{
b = 2;
}

//第三种
if(a <=1 && b <=1)
{
printf("%ld\n",count);
continue;
}

//可能输入的a比b要大 则交换
if(a > b)
{
long temp = a;
a = b;
b = temp;
}

//考虑两种特殊情况 其一
if(2 == a && b >=4)
{
count += 2;
a += 2;
}

//特殊情况 其二
if(2 == a && b < 4)
{
count += b - a + 1;
printf("%ld\n",count);
continue;
}

//使得下面的判断只会判断奇数 偶数除2外 都不是素数
if(0 == a % 2)
{
if(a == 2)
{
count++;
}
a += 1;
}
for(i=a;i<=b;)
{
if(flag[i])
{
count++;
}
i += 2; //步长为2
}

printf("%ld\n",count);
}


return 0;
}


显然没压力啦 AC了
crakme 2011-09-15
  • 打赏
  • 举报
回复
楼主你那求素数的方法的思想是想到了,不过没用好,题目的数据规模不是只有1000000,你弄个大于1000000的数组有什么意义呢?
用从a(a>=2,1肯定是素数了)开始到b的平方根(取整)依次求余,因为到了平方根以后,再增加除数,得到的商是小于平方根的,等于以前取过的除数,所以平方根以后不用再算了。
当然还有更快的Fermat定理,伪素数算法。
AndyZhang 2011-09-15
  • 打赏
  • 举报
回复
这个不难吧?线性筛选素数,这不就才100万么,很快的。基本上是o(n)。然后直接求也行,打表记录当前有多少个也行。
gnosis 2011-09-15
  • 打赏
  • 举报
回复
预处理 先线性晒素数1000000 logn复杂度
然后 统计下每个数 0-count之间素数个数 O(n)复杂度
之后就是 就是count【m】-count【n】
hondely 2011-09-15
  • 打赏
  • 举报
回复
void eratosthenes() {
notprime[0][0] = notprime[1][0] = true;
for (int i = 2; i*i <= MAX; i++) {
if (notprime[i][0]) continue;
for (int j = i*i; j <= MAX; j += i) notprime[j][0] = true;
}
}

高速查找素数方法
oracleapple 2011-09-15
  • 打赏
  • 举报
回复
用C++提交下面程序 wrong answer
#include<stdio.h>
#include<math.h>
int main(void)
{
int cases;
long a,b,i,j,c,count;
bool flag[1011000];
flag[0] = true;

for(i=1;i<1011000;i++)
{
if(i <= 3)
{
flag[i] = true;
continue;
}

if(0 == i % 2)
{
flag[i] = false;
continue;
}

c = (long)sqrtl((long double)i);

for(j=2;j<=c;j++)
{
if(0 == i % j)
{
flag[i] = false;
break;
}

if(c == j)
{
flag[i] = true;
break;
}
}
}
scanf("%d",&cases);

while(cases--)
{
count = 0;
scanf("%ld%ld",&a,&b);


for(i=a;i<=b;i++)
{
if(flag[i])
{
count++;
}
}

printf("%ld\n",count);

}


return 0;
}

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧