16,749
社区成员
发帖
与我相关
我的任务
分享
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.