编码挑战:求一千万自然数中质数和

2016-02-24 22:25:54 +08:00
 SlipStupig

语言只能用 python ,求一千万自然数总质数总和,速度最快的有奖励哦

5377 次点击
所在节点    Python
35 条回复
ilcwd23
2016-02-24 22:49:18 +08:00
打表?
whisperzzzz
2016-02-24 23:05:22 +08:00
3203324994356
auser
2016-02-24 23:13:10 +08:00
速度最快的难道不是直接打印结果?
不知道哪本书有写过哪个美国大学举办了类似比赛,然后……第一名开销是负数。
mickeyandkaka
2016-02-24 23:20:22 +08:00
congeec
2016-02-24 23:35:54 +08:00
knightdf
2016-02-24 23:37:45 +08:00
那 CPU 多的赢了,判断 2-sqrt(n)就行了
congeec
2016-02-24 23:44:42 +08:00
@auser 卡内基梅隆大学编程难题
ianluo
2016-02-24 23:49:54 +08:00
@ilcwd23 神马意思?
random2case
2016-02-25 00:18:49 +08:00
private static final int MAX = 100000000;
private static final int ARRAY_SIZE = (int) Math.round((MAX * 1.1) / Math.log(MAX));
private static int[] array = new int[ARRAY_SIZE];
//--//
int pos = 0;
array[pos++] = 2;

int sqrtN = 3;
int countSqrtN = 2;

for (int i = 3; i < MAX; i += 2) {
for (int j = 0; j < pos; j++) {
int value = array[j];
if (value > sqrtN) {
premier = true;
break;
}
if ((i % value) == 0) {
premier = false;
break;
}
}

if (premier) {
array[pos++] = i;
}

if (--countSqrtN == 0) {
countSqrtN = sqrtN;
sqrtN++;
}
}


给一个 java 版的吧,暂时找不到当时 python 写的了,自己改编一下吧
whisperzzzz
2016-02-25 00:22:04 +08:00
@congeec 几个月前看这个 DP 觉得简直丧心病狂……
whisperzzzz
2016-02-25 00:24:31 +08:00
@knightdf 判断单个的话可以 Miller-Rabin ,多取几个数就好了……
XiaoxiaoPu
2016-02-25 00:39:34 +08:00
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


static inline int getbit(int *bits, int i)
{
return (bits[i>>5] >> (i & 31)) & 1;
}

static inline void setbit(int *bits, int i)
{
bits[i>>5] |= (1 << (i & 31));
}

static inline void clrbit(int *bits, int i)
{
bits[i>>5] &= ~(1 << (i & 31));
}

int isqrt(int num)
{
register int x1 = num, x2;

do
{
x2 = x1;
x1 = (x1 + num / x1) / 2;
} while (x1 < x2);
return x2;
}


int main()
{
int n = 10000000;
int *bits;

bits = (int *)malloc(((n>>5)+1) * sizeof(int));
if (bits == NULL)
{
fprintf(stderr, "Out of memory.\n");
return 1;
}

for (int i = 0; i < ((n>>5)+1); i++)
{
bits[i] = ~0;
}

clrbit(bits, 0);
clrbit(bits, 1);
clrbit(bits, 4);

int end = isqrt(n);
long sum = 0;
for (int i = 2; i <= end; i++)
{
if (getbit(bits, i))
{
sum += i;
int j0 = n / i;
for (int j = 2; j <= j0; j++)
{
clrbit(bits, i * j);
}
}
}

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

return 0;
}



发个 C 写的
➜ ~ gcc -o prime -std=gnu99 -O3 prime.c
➜ ~ time ./prime
642869
./prime 0.04s user 0.00s system 94% cpu 0.046 total
➜ ~
XiaoxiaoPu
2016-02-25 00:41:39 +08:00
啊哦,上面发的错了,这个才对

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


static inline int getbit(int *bits, int i)
{
return (bits[i>>5] >> (i & 31)) & 1;
}

static inline void setbit(int *bits, int i)
{
bits[i>>5] |= (1 << (i & 31));
}

static inline void clrbit(int *bits, int i)
{
bits[i>>5] &= ~(1 << (i & 31));
}

int isqrt(int num)
{
register int x1 = num, x2;

do
{
x2 = x1;
x1 = (x1 + num / x1) / 2;
} while (x1 < x2);
return x2;
}


int main()
{
int n = 10000000;
int *bits;

bits = (int *)malloc(((n>>5)+1) * sizeof(int));
if (bits == NULL)
{
fprintf(stderr, "Out of memory.\n");
return 1;
}

for (int i = 0; i < ((n>>5)+1); i++)
{
bits[i] = ~0;
}

clrbit(bits, 0);
clrbit(bits, 1);
clrbit(bits, 4);

int end = isqrt(n);
for (int i = 2; i <= end; i++)
{
if (getbit(bits, i))
{
int j0 = n / i;
for (int j = 2; j <= j0; j++)
{
clrbit(bits, i * j);
}
}
}

long sum = 0;
for (int i = 2; i <= n; i++)
{
if (getbit(bits, i))
{
sum += i;
}
}
printf("%ld\n", sum);

return 0;
}


➜ ~ gcc -o prime -std=gnu99 -O3 prime.c
➜ ~ ./prime
3203324994356
➜ ~
msg7086
2016-02-25 03:46:02 +08:00
好没挑战啊。某节大二课后作业就是用 pthread 做并行筛法求质数, INTMAX 之内的所有质数,最后求总数。这个改成求和也并不难,把统计时候的 cnt++ 改成 sum+=x 就行了。
msg7086
2016-02-25 03:50:49 +08:00
另外这题目也太不规范了。比如「自然数范围内任意一千万个数字」,自然数范围大了,难道要支持几万位的数字?
sinxccc
2016-02-25 04:19:32 +08:00
@auser "Expert C Programming: Deep C Secrets" 里的段子。
SlipStupig
2016-02-25 08:13:54 +08:00
@msg7086 大整数加减有何不可,你代码够优秀放出来
em70
2016-02-25 08:53:02 +08:00
任意 1000 万个数字,不一定是连续的数字吧,不一定没有重复吧,也就是说是包含 1000 万个无规律数字的数组中求质数总和?
SlipStupig
2016-02-25 09:04:56 +08:00
@em70 很正确
knightdf
2016-02-25 09:17:11 +08:00
@whisperzzzz 这个好像是更专业

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/258901

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX