- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试解决问题 PRIME1使用埃拉托色尼分段筛。我的程序可以正常使用达到 NEW_MAX
的普通筛子。但是在 n > NEW_MAX
情况下存在一些问题,其中分段筛分发挥作用。在这种情况下,它只打印所有数字。这是带有相关测试用例的代码的链接:http://ideone.com/8H5lK#view_edit_box
/* segmented sieve */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX_LIMIT 1000000000 //10^9
#define NEW_MAX 31623 /*SQUARE ROOT OF 1000000000*/
#define MAX_WIDTH 100000 //10^5
char flags[NEW_MAX+100]; /*TO PREVENT SEGMENTATION FAULT*/
void initialise(char flagarr[], long int n) //initialise all elements to true from 1 to n
{
long int i;
for (i = 1; i <= n; i++)
flagarr[i] = 't';
}
void sieve(unsigned long long m, unsigned long long n, char seg_flags[])
{
unsigned long long p, i, limit;
if (m == 1)
seg_flags[1] = 'f';
/*Seperate inner loop for p=2 so that evens are not iterated*/
for (i = 4; i >= m && i <= n; i += 2)
{
seg_flags[i-m+1] = 'f';
}
if (seg_flags == flags)
limit = NEW_MAX;
else
limit = sqrt(n);
for (p = 3; p <= limit+1; p += 2) //initial p+=2 bcoz we need not check even
{
if (flags[p] == 't')
{
for (i = p*p; i >= m && i <= n; i += p) //start from p square since under it would have been cut
seg_flags[i-m+1] = 'f'; /*p*p, p*p+p, p*p + 2p are not primes*/
}
}
}
void print_sieve(unsigned long long m,unsigned long long n,char flagarr[])
{
unsigned long long i;
if (flags == flagarr) //print non-segented sieve
{
for (i = m; i <= n; i++)
if (flagarr[i] == 't')
printf("%llu\n", i);
}
else
{
//print segmented
for (i = m; i <= n; i++)
if (flagarr[i-m+1] == 't')
printf("%llu\n", i);
}
}
int main()
{
unsigned long long m, n;
int t;
char seg_flags[MAX_WIDTH+100];
/*setting of flags for prime nos. by sieve of erasthromas upto NEW_MAX*/
initialise(flags, NEW_MAX);
flags[1] = 'f'; /*1 is not prime*/
sieve(1, NEW_MAX, flags);
/*end of initial sieving*/
scanf("%d", &t);
while (t--)
{
scanf("%llu %llu", &m, &n);
if (n <= NEW_MAX)
print_sieve(m, n, flags); //NO SEGMENTED SIEVING NECESSARY
else if (m > NEW_MAX)
{
initialise(seg_flags, n-m+1); //segmented sieving necessary
sieve(m, n, seg_flags);
print_sieve(m, n, seg_flags);
}
else if (m <= NEW_MAX && n > NEW_MAX) //PARTIAL SEGMENTED SIEVING NECESSARY
{
print_sieve(m, NEW_MAX, flags);
/*now lower bound for seg sieving is new_max+1*/
initialise(seg_flags, n-NEW_MAX);
sieve(NEW_MAX+1, n, seg_flags);
print_sieve(NEW_MAX+1, n, seg_flags);
}
putchar('\n');
}
system("pause");
return 0;
}
更新:感谢丹尼尔的回复。我实现了你的一些建议,我的代码现在产生了正确的输出:-
/*segmented sieve*/
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#define MAX_LIMIT 1000000000 /*10^9*/
#define NEW_MAX 31623 /*SQUARE ROOT OF 1000000000*/
#define MAX_WIDTH 100000 /*10^5*/
int flags[NEW_MAX+1]; /*TO PREVENT SEGMENTATION FAULT goblal so initialised to 0,true*/
void initialise(int flagarr[],long int n)
/*initialise all elements to true from 1 to n*/
{
long int i;
for(i=3;i<=n;i+=2)
flagarr[i]=0;
}
void sieve(unsigned long m,unsigned long n,int seg_flags[])
{
unsigned long p,i,limit;
/*Seperate inner loop for p=2 so that evens are not iterated*/
if(m%2==0)
i=m;
else
i=m+1;
/*i is now next even > m*/
for(;i<=n;i+=2)
{
seg_flags[i-m+1]=1;
}
if(seg_flags==flags)
limit=NEW_MAX;
else
limit=sqrt(n);
for(p=3;p<=limit+1;p+=2) /*initial p+=2 bcoz we need not check even*/
{
if(flags[p]==0)
{
for(i=p*p; i<=n ;i+=p)
/*start from p square since under it would have been cut*/
{
if(i<m)
continue;
seg_flags[i-m+1]=1;
/*p*p, p*p+p, p*p + 2p are not primes*/
}
}
}
}
void print_sieve(unsigned long m,unsigned long n,int flagarr[])
{
unsigned long i;
if(m<3)
{printf("2\n");m=3;}
if(m%2==0)
i=m+1;
else
i=m;
if(flags==flagarr) /*print non-segented sieve*/
{
for(;i<=n;i+=2)
if(flagarr[i]==0)
printf("%lu\n",i);
}
else {
//print segmented
for(;i<=n;i+=2)
if(flagarr[i-m+1]==0)
printf("%lu\n",i);
}}
int main()
{
unsigned long m,n;
int t;
int seg_flags[MAX_WIDTH+100];
/*setting of flags for prime nos. by sieve of erasthromas upto NEW_MAX*/
sieve(1,NEW_MAX,flags);
/*end of initial sieving*/
scanf("%d",&t);
while(t--)
{
scanf("%lu %lu",&m,&n);
if(n<=NEW_MAX)
print_sieve(m,n,flags);
/*NO SEGMENTED SIEVING NECESSARY*/
else if(m>NEW_MAX)
{
initialise(seg_flags,n-m+1);
/*segmented sieving necessary*/
sieve(m,n,seg_flags);
print_sieve(m,n,seg_flags);
}
else if(m<=NEW_MAX && n>NEW_MAX)
/*PARTIAL SEGMENTED SIEVING NECESSARY*/
{
print_sieve(m,NEW_MAX,flags);
/*now lower bound for seg sieving is new_max+1*/
initialise(seg_flags,n-NEW_MAX);
sieve(NEW_MAX+1,n,seg_flags);
print_sieve(NEW_MAX+1,n,seg_flags);
}
putchar('\n');
}
system("pause");
return 0;
}
但是我下面的筛选函数进一步考虑了你的其他建议会产生不正确的输出:-
void sieve(unsigned long m,unsigned long n,int seg_flags[])
{
unsigned long p,i,limit;
p=sqrt(m);
while(flags[p]!=0)
p++;
/*we thus get the starting prime, the first prime>sqrt(m)*/
if(seg_flags==flags)
limit=NEW_MAX;
else
limit=sqrt(n);
for(;p<=limit+1;p++) /*initial p+=2 bcoz we need not check even*/
{
if(flags[p]==0)
{
if(m%p==0) /*to find first multiple of p>=m*/
i=m;
else
i=(m/p+1)*p;
for(; i<=n ;i+=p)
/*start from p square since under it would have been cut*/
{
seg_flags[i-m+1]=1;
/*p*p, p*p+p, p*p + 2p are not primes*/
}
}
}
}
最佳答案
你的问题是
for (i = 4; i >= m && i <= n; i += 2)
for (i = p*p; i >= m && i <= n; i += p)
如果范围的下限为 4 或更小,您只会消除 2 的倍数,并且您只会消除大于 sqrt(m)
的素数倍数.删除 i >= m
退出循环条件并将其替换为 if (i < m) { continue; }
在循环体中(更好的是,直接计算 p
的第一个倍数不小于 m
并完全避免这种情况)。
而不是使用 't'
和 'f'
作为标志,使用 1
和 0
正如 DMR 的意图,这将得到更好的理解。
重新更新:这个
/*Seperate inner loop for p=2 so that evens are not iterated*/
if(m%2==0)
i=m;
else
i=m+1;
/*i is now next even > m*/
for(;i<=n;i+=2)
如果m == 2
会伤害你.如果m == 2
, 您必须以 i = 4
开头.
关于
unsigned long p,i,limit;
p=sqrt(m);
while(flags[p]!=0)
p++;
/* snip */
for(;p<=limit+1;p++)
看来你误解了我的意思,“你只消除了大于 sqrt(m)
的素数的倍数”并不意味着你不需要消除更小的素数的倍数,这意味着你的初始版本没有,这导致范围内的几乎所有数字都没有消除。您应该使用 p = 2
开始外循环- 或者对 2 的倍数进行单独的传递,并以 3 开始该循环,递增 p
2,并在 p*p
中较大的位置开始内循环和 p
的最小倍数不少于 m
.后者的代码有效,因此将其包装在
if ((i = p*p) < m) {
/* set i to smallest multiple of p which is >= m */
}
会起作用(您可以避免分支并仅使用一个除法使其更快一些,但差异会很小)。
最后,您选择用 0 和 1 表示的内容是不规范的,这是 C,因此 0 在条件下的计算结果为 false,而其他所有内容都为 true,因此规范的替换应该是 't' -> 1
和 'f' -> 0
在这样的上下文中,数组条目是标志,人们会检查
if (flags[p]) // instead of: if (flags[p] != 0)
if (!flags[p]) // instead of: if (flags[p] == 0)
也无需更改 char[]
中的数组类型至 int[]
, char
也是整数类型,所以 0 和 1 完全没问题 char
值。数组类型的选择会影响性能。一方面,int
- 大小的加载和存储通常比字节大小的加载和存储更快,因此这有利于 int flags[]
甚至 long int flags[]
用于字大小的读写。另一方面,较小的 char flags[]
你会得到更好的缓存位置。如果每个标志使用一个位,您将获得更好的缓存局部性,但这会使读取/设置/清除标志的速度仍然变慢。什么能产生最佳性能取决于筛子的结构和尺寸。
关于c - Spoj PRIME1 使用埃拉托色尼筛(在 C 中),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9362177/
以下是 SPOJ GCD2 的代码.它在我的机器和 Ideone 上运行良好,但在 SPOJ 上出现运行时错误 (SIGFPE)。我已经检查了 spojtoolkit.com 上也提供的所有测试用例。
如果正整数在从左到右和从右到左读取时在十进制系统中的表示相同,则称为回文。给定一个不超过1000000位的正整数K,写出大于K的最小回文的值输出。显示的数字始终不带前导零。 输入 第一行包含整数 t,
我一直在努力解决这个问题 SPOJ www.spoj.com/problems/PRHYME/?几天了,但没有成功。这是问题的简要说明: Given is a wordlist L, and a
我是编码初学者。我在向 spoj 提交质数生成代码时收到 NZEC 错误。但代码在我的桌面上运行得很好。请帮助我。这就是我编写的代码。 import java.util.*; import java.
#include #include #include main() { int n, m, i, j, k; char a[100], b[100]; scanf("%d
我遇到了一个问题 SPOJ . 我检查了所有通过所有测试用例,但我仍然在 spoj 上得到“WA”。 我知道它可以使用动态编程来解决,但我正在练习内存。 这是我的代码: #include #inclu
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
有关确切的问题,请参阅此 link 这里我定义了三个函数,将它们相互调用。函数调用尚未完成 #include int primegen(int x1,int x2); int isprime(int
Peter 想生成一些 prime numbers对于他的密码系统。帮助他!您的任务是生成两个给定数字之间的所有素数! 输入 输入以单行中测试用例的数量t开始(t int main() {
http://www.spoj.com/problems/FCTRL2/ 我的代码在 Spoj 中显示编译错误,尽管在我的编译器中运行准确。 **IDE - 代码块 ** int cal(int );
我正在尝试将我的代码提交给 SPOJ 上的“小阶乘”问题。它在我的 IDE 上成功运行,但在 SPOJ 上显示运行时错误 (NZEC)。请提出解决方案。 import java.util.Scanne
我正在尝试解决 SPOJ 中的下一个回文问题。我在下面的 Java 代码中收到超出时间限制的错误。 “如果一个正整数在十进制中从左到右和从右到左读的表示相同,则称为回文。对于给定不超过 1000000
我在 spoj 上解决了一个名为 Ambiguous Permutations(http://www.spoj.com/problems/PERMUT2/)的简单问题,当我测试小输入时它工作正常,但在
我正在尝试关于 SPOJ 的问题,其中我们必须简单地找到 Longest Increasing Sub-sequence 的长度给定数组 A. 我使用动态规划 O(n^2) 算法解决了这个问题,解决方
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 3 年前。 Improve this qu
我刚开始接触竞争性编程。我有点坚持这个素数。 SPOJ 上的生成器问题。代码在 GeeksforGeeks IDE 上运行良好,但在 SPOJ 上它会出现运行时错误。问题是这样的: Peter 想为他
好吧,这让我发疯了。我在 spoj 上解决了一个名为 MIXTURES ( http://www.spoj.com/problems/MIXTURES/) 的问题。我不知道为什么我总是遇到段错误。该问
我已经为下一个回文问题编写了一个蛮力解决方案,并希望获得 Time Limit Exceeded 。但是当我测试了一些测试用例时它工作正常但是当我在 spoj 中提交代码时我得到了错误的答案。这是我的
我正在尝试解决 NGON问题。我在这里使用自下而上的动态编程。递归函数为: f(a,b) = f(a-1,b) + f(a-1,b-1)*ai +f(a-1,b-2)*ai*(ai-1)/2, a>0
我正在解决这个 spoj 问题。 http://www.spoj.com/problems/MAXSUB/我所有的测试用例都正常工作,但我在 spoj 中得到了错误的答案。我试图改变我的代码很多但仍然
我是一名优秀的程序员,十分优秀!