Google Treasure Hunt 2008 素数

ahjoe 2008-12-24 05:55:02
题目:连续 5 个素数之和
连续 13 个素数之和
连续 275 个素数之和
连续 1187 个素数之和
求出同时符合以上4个条件的数。

技巧:用数组里的一个位保存一个数是否是素数。
结果:5615741
计算用时:17秒 (AMD 2600+)


unit GoogleHunt5u;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls, Spin, SearchDir;

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Label3: TLabel;
Label2: TLabel;
Edit3: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

function IsPrime(V: DWORD): Boolean;

implementation

{$R *.DFM}

var
bitArr: array [0..HIGH(DWORD) div 32] of DWORD;

InitMax: DWORD = 3;

function IsPrimeFromBit(V: DWORD): Boolean;
var
p: integer; // 下标
m: integer; // 余
mask: DWORD;
begin
if V = DWORD(-1) then
sleep(0); // ERROR
while InitMax < V do
begin
if IsPrime(InitMax + 2) then
begin
Inc(InitMax, 2);
p := InitMax shr 5;
m := InitMax and $1F;
mask := 1 shl m;
bitArr[p] := bitArr[p] or mask;
end
else
Inc(InitMax, 2);
end;
p := V shr 5;
m := V and $1F;
if m = 0 then
begin
Result := False;
Exit;
end;
mask := 1 shl m;
if p < 0 then
Sleep(1);
Result := bitArr[p] and mask <> 0;
end;

function IsPrime(V: DWORD): Boolean;
var
i: integer;
max: DWORD;
begin
max := Round(Sqrt(V));
i := 3;
while i <= max do
begin
if IsPrimeFromBit(i) then
if V mod i = 0 then
begin
Result := False;
Exit;
end;
Inc(i);
end;
Result := True;
end;

function NprePrime(V: DWORD; n: integer): integer;
begin
if IsPrimeFromBit(V) then
Dec(n, 2)
else
Dec(n);
Dec(V);
while n > 0 do
begin
if IsPrimeFromBit(V) then
begin
Dec(n);
if n = 0 then
begin
Result := V;
Exit;
end;
end;
Dec(V);
if V = 2 then
begin
Result := V;
Exit;
end
end;
end;

function GetNextPrime(V: DWORD): DWORD;
begin
Inc(V);
while not IsPrimeFromBit(V) do
begin
Inc(V);
end;
Result := V;
end;

function SumNPrime(V: DWORD; n: integer): DWORD;
begin
Result := V;
Dec(n);
while n > 0 do
begin
V := GetNextPrime(V);
Inc(Result, V);
Dec(n);
end;
end;

function IsNPrimeSum(V: DWORD; n: integer): Boolean;
var
stV: DWORD;
sumN: DWORD;
begin
stV:= NprePrime((V div n), n);
repeat
sumN := SumNPrime(stV, n);
stV := GetNextPrime(stV);
until sumN >= V;
Result := sumN = V;
end;

procedure TForm1.Button1Click(Sender: TObject);
label repgo;
const
Cnt1 = 5;
Cnt2 = 13;
Cnt3 = 275;
Cnt4 = 1187;
var
stV: DWORD;
st: DWORD;
begin
st := GetTickCount();
stV := SumNPrime(2, Cnt4);
while True do
begin
Edit1.Text := 'Calc... ' + IntToStr(stV);
Application.ProcessMessages();
if IsNPrimeSum(stV, Cnt1) then
if IsNPrimeSum(stV, Cnt2) then
if IsNPrimeSum(stV, Cnt3) then
if IsNPrimeSum(stV, Cnt4) then
begin
Edit1.Text := IntToStr(stV);
Break;
end;
if stV and 1 = 0 then // 偶数
Inc(stV)
else
Inc(stV, 2);
end;
st := GetTickCount() - st;
Edit3.Text := IntToStr(st div 1000);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
FillChar(bitArr, sizeof(bitArr), 0);
bitArr[0] := $C; // 2,3 are Prime
end;

end.
...全文
59 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

16,749

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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