奇怪于某些人的大脑结构:),筛法争论

fixopen 2006-03-21 06:17:35
lifeNet(19710496) 17:58:34
lifeNet 17:26:08
筛法不复杂。基本思路是找到一个数,用所有的小于它的素数去除,如果整除就不是素数,反之就是。
lifeNet 17:27:40
2是素数。
3除以2, 不整除,素数。
4除以2,整除,pass。
5除以2,不整除,除以3,不整除,素数。注意,这儿并不试4,只试所有的素数,以下相同。
6……,就是如此,明白?
笑小子(12686718) 17:52:20
这不是筛数法
lifeNet(19710496) 18:00:02
这就是筛法。
笑小子(12686718) 17:53:59
肯定不是
笑小子(12686718) 17:54:05
你去网上搜索筛数法
SErAph(495664560) 17:54:11
怎样才算是?
笑小子(12686718) 17:54:20
网上很多例子的
笑小子(12686718) 17:54:23
GOOGLE一下
lifeNet(19710496) 18:01:49
名字起源于中国古代(张衡?还是某人)用的延圆环顺序排列的数表,把不是素数的捅掉,剩下的跟一个筛子是的,故称筛法。
笑小子(12686718) 17:55:28
是啊
lifeNet(19710496) 18:02:24
你最好看清楚我说的,然后再评价。或许你没有看懂呢?
笑小子(12686718) 17:55:57

笑小子(12686718) 17:56:00
你说的根本不是
笑小子(12686718) 17:56:29
筛数法是
一开始生成一个范围内的数
然后去掉2的倍数
接着去掉3的倍数
笑小子(12686718) 17:56:33
依次类推
笑小子(12686718) 17:56:41
这才是筛数法
笑小子(12686718) 17:56:56
当然实际使用并不仅仅这样
还会有些优化
笑小子(12686718) 17:57:03
比如4就不会被选做筛子
笑小子(12686718) 17:57:14
只有质数才被被选做筛子
lifeNet(19710496) 18:06:52
呵呵,原来你也懂啊,那你再看看我的算法,ok?
笑小子(12686718) 18:00:52
你那是每个数,把已经求出的质数去试除
笑小子(12686718) 18:01:00
这也是种方法
但是不是筛数法
笑小子(12686718) 18:02:10
5除以2,不整除,除以3,不整除,素数。注意,这儿并不试4,只试所有的素数,以下相同。
6……,就是如此,明白?

筛法除完2,不整除,就前进到6了
哪还会算5除3
笑小子(12686718) 18:02:21
要不就是你没描述清楚
lifeNet(19710496) 18:10:28
哥们,你在好好想想,筛法可以以二为因子把所有他的倍数筛掉,那么,如果我仅仅要判断其中一个数,我怎么筛他呢?
笑小子(12686718) 18:04:19

笑小子(12686718) 18:04:23
算了
懒得说了
lifeNet(19710496) 18:10:58
5当然要除以3,否则你怎么能确定不被筛掉?
笑小子(12686718) 18:04:48
2先要筛除所有2的倍数后,才会以3为筛子
笑小子(12686718) 18:05:04
也就是说,先算的5/2,6/2,7/2。。。。。。
lifeNet(19710496) 18:11:36
比如一个33,你用2试一下,如果不能整除,不用3试了?
笑小子(12686718) 18:05:12
然后才是5/3,6/3,7/3
笑小子(12686718) 18:05:20
这才叫筛数法


大家说,这究竟怎么回事?为什么他就是不承认这是筛法呢?他也很清楚筛法呀。
...全文
802 49 打赏 收藏 转发到动态 举报
写回复
用AI写文章
49 条回复
切换为时间正序
请发表友善的回复…
发表回复
Promedini 2006-05-13
  • 打赏
  • 举报
回复
狂晕

接分
xuelong_zl 2006-04-17
  • 打赏
  • 举报
回复
不过水还是一定要灌的.....

xuelong_zl 2006-04-17
  • 打赏
  • 举报
回复
5555555,代码没一个能看懂的,能不能写得简单点......

乱乱的不知道在讨论啥

一个是筛一个数分解因子,一个是筛整数集合

不知道大家是在讨论筛法的思想本身还是在讨论对某一问的实现.......

汗了............
TERRYYRRET 2006-04-17
  • 打赏
  • 举报
回复
帮顶

接分
chenhu_doc 2006-04-16
  • 打赏
  • 举报
回复
哈哈,看了,好有意思··· 同情中········
defyer007 2006-04-16
  • 打赏
  • 举报
回复
mark
GaoXX 2006-04-15
  • 打赏
  • 举报
回复
顶一下
fiftymetre 2006-03-25
  • 打赏
  • 举报
回复
可怜的笑小子。。。。。
  • 打赏
  • 举报
回复
你的东西俺是不会, 不过如果 LZ 的第一个程序也能算筛法的话, 可能人都笑死了, 下面这个应该能算筛法, 我实在看不出跟 LZ 的程序有什么相同的地方:


{$APPTYPE CONSOLE}
{$R-,S-,Q-,O-}

program prime;

uses sysutils, windows;

const
maxn = int64(10) shl 30;
maxlen = 10000;
m = 6;
dots = 80;

type
Pls = ^Tls;
Tls = array[byte] of byte;

var
mask: pointer;
primes, mprimes, ans: array[1 .. maxlen] of integer;
bits: array[byte] of integer;
len, r: integer;
start: TDateTime;

procedure solve(const a, b, c: integer; var x, y: integer);
begin
if a = 0 then begin
x := 0; y := c div b;
end else begin
solve(b mod a, a, c, y, x);
x := x - b div a * y;
end;
end;

procedure init;
var
p, k: integer;
begin
k := 2; len := 0;
repeat
len := len + 1; primes[len] := k;
repeat
k := k + 1; p := 1;
while (sqr(primes[p]) < k) and (k mod primes[p] <> 0) do p := p + 1;
until k mod primes[p] <> 0;
until 1.0 * k * k > maxn;
bits[0] := 0; for k := 1 to $FF do bits[k] := bits[k shr 1] + k and 1;
end;

procedure makeprimes;
var
i, k, n, size, kmax, min, last, p, x, dot: integer;
begin
n := 1; for i := 1 to m do n := n * primes[i];
for i := m + 1 to len do begin
p := primes[i]; solve(p, - n, 1, x, mprimes[i]);
mprimes[i] := (mprimes[i] mod p + p) mod p;
end;
r := len; size := (maxn div n + 7) shr 3; last := 0; dot := 0;
fillchar(ans, sizeof(ans), 0); getmem(mask, size);
for i := 1 to n - 1 do begin
k := 1; while (k < m) and (i mod primes[k] <> 0) do k := k + 1;
if i mod primes[k] = 0 then continue;
p := i - last; last := i; kmax := (maxn - i) div n;
for k := m + 1 to len do ans[k] := (ans[k] + mprimes[k] * p) mod primes[k];
fillchar(mask^, size, 0);
for k := m + 1 to len do begin
p := primes[k];
if ans[k] = 0 then min := p - 1 else min := ans[k] - 1;
asm
mov EAX, mask
mov EBX, kmax
mov ECX, min
mov EDX, p
@001:
BTS [EAX], ECX
add ECX, EDX
cmp ECX, EBX
jl @001
end;
end;
for k := 0 to size - 1 do kmax := kmax - bits[Pls(mask)^[k]];
r := r + kmax;
if i / n > dot / dots then begin
dot := dot + 1; write('.');
end;
end;
freemem(mask, size);
writeln;
end;

begin
start := now;
init;
makeprimes;
messageboxA(0,
PChar(Format('sum = %d, Time = %.2f',
[r, (now - start) * SecsPerDay])),
'prime', 0);
end.

dot99 2006-03-24
  • 打赏
  • 举报
回复
按照楼主的算法,省略了原始描述中,在interval之间用if判断是否要略过已经筛除的数
因为在vector全部是素数,没必要去判断

就因为空间上这么个变化,就不是筛法了...服你了

形式主义,教条主义,呵呵
dot99 2006-03-24
  • 打赏
  • 举报
回复
对于你的 2^30402457 - 1

用Miller-Rabin方法来测试是否为素数,恐怕更好

筛法空间消耗非常大

如果用你的去筛,恐怕就更大了...

难道你看不出楼主的算法么
dot99 2006-03-24
  • 打赏
  • 举报
回复
to DiabloWalkOnTheEarth: 我写的scheme版本,你看是不是一样的--;

(define (generatePrime n)
(define (addtoPrimeTable tbl p)
(append tbl (list p)))
(define (canCross? tbl c)
(letrec ((limit (sqrt c))
(canCrossNextPrime?
(lambda (next_tbl count)
(if (> count limit)
#t
(if (= 0
(remainder c (car next_tbl)))
#f
(canCrossNextPrime?
(cdr next_tbl)
(+ count 1)))))))
(canCrossNextPrime? tbl 1)))
(define (iter tbl c)
(if (> c n)
tbl
(iter (if (canCross? tbl c)
(addtoPrimeTable tbl c)
tbl)
(+ c 1))))
(iter '(2) 3))

(generatePrime 100)

你会说我这个不是筛法?
  • 打赏
  • 举报
回复
贴个世界上最最 BC 的筛法求 1E8 范围素数的程序, 连2的倍数都没有首先排除的, 相信很难有人能写得跑的比这更慢了, 求出 1E8 的筛子用时共 7 秒(PM1.4G), 我认为筛法也就能对付 1E16 范围内的数, 因此我认为生成筛子的时间可以忽略不计:

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

#define MAXX (100000000 )
#define SQRX (10000)
#define BUFL (MAXX/8+1)

unsigned char f [ BUFL ];
int b [ 256 ];

int main()
{
int i , j , c = 0;
time_t t = time( NULL );
for( i = 0; i < 256; ++i )
for( j = 0; j < 8; ++j )
if( i & (1<<j) ) ++b[i];
memset( f , 0xff , MAXX / 8 );
f[0] &= 0xfc;
for( i = MAXX & ~7 ; i < MAXX ; ++i )
f[ i / 8 ] |= 1 << ( i % 8 );
for( i = 2; i < SQRX; ++i )
{
if( (f[i/8] & ( 1 << (i%8) )) == 0 ) continue;
for ( j = i * i ; j < MAXX ; j += i )
f[j/8] &= ~( 1 << ( j % 8 ) );
}
for( i = 0; i < BUFL; ++i )
c+=b[ f[i] ];
printf( "c == %d \n t == %d\n" , c , time(NULL) - t );

return 0;
}

dot99 2006-03-24
  • 打赏
  • 举报
回复
(define (prime? x)
(if (even? x)
#f
(letrec ((tbl (generatePrime
(inexact->exact (floor (sqrt x)))))
(canCross?
(lambda (tbl)
(if (null? tbl)
#t
(if (= 0 (remainder x (car tbl)))
#f
(canCross? (cdr tbl)))))))
(canCross? tbl))))

这是检测的
dot99 2006-03-24
  • 打赏
  • 举报
回复
sqrt(100) == 10, 这是我的疏忽
2 3 5 7 是可以筛到 100 ,看我刚才17:22:00的贴
dot99 2006-03-24
  • 打赏
  • 举报
回复
我的讨论到此结束~~可能家里不能上网,星期一回来继续关注
  • 打赏
  • 举报
回复
拜托, 2 3 5 7 可以筛到 100 , 100 以内的素数可以筛到 1E4 , 1E4 内的素数可以筛到 1E8 , 1E8 内的素数基本上可以筛到筛法能够对付的全部区间了, 而生成 1E8 的素数我相信用最 BC 的办法也可以在1秒内得出来.

"筛的生成才是最耗时间的吧" 这句话你也能讲出来, 我基本上要晕倒了, 你试试在 2秒内生成 1E16 的素数给我看看...

晕, 怎么最近总是在 CSDN 碰到神仙级的妖怪啊 ....
dot99 2006-03-24
  • 打赏
  • 举报
回复
看原始描述中,从2开始到sqrt(N)之间的筛的生成,只不过把除的过程,预先变成标记p*i为false的时间罢了
那跟现在的,从2开始,其他的数p'用通过sqrt(p')(注意是sqrt(p'),不是所有的筛)的筛,来决定p'是否加入筛

两个生成过程,有什么区别呢?
dot99 2006-03-24
  • 打赏
  • 举报
回复
晕。。。。筛的生成才是最耗时间的吧
2 3 5 7能准确的筛的数只有到53吧
若这个数很大呢,就需要生成,假设只知道2是素数,从2开始生成筛

生成筛的时间耗费 和 已知筛的筛选过程的时间耗费

谁比较多?
  • 打赏
  • 举报
回复
上面搞错了, 分段以后的时间复杂度也是 O ( N * lnln( N ) ) 或者略低..
加载更多回复(29)

15,440

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 非技术区
社区管理员
  • 非技术区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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