221 lines
4.3 KiB
ObjectPascal
221 lines
4.3 KiB
ObjectPascal
{$IFDEF FPC}{$MODE DELPHI}{$ELSE}{$APPTYPE CONSOLE}{$ENDIF}
|
|
uses
|
|
sysutils;
|
|
const
|
|
MAXPROPERDIVS = 1920;
|
|
type
|
|
tRes = array[0..MAXPROPERDIVS] of LongWord;
|
|
tPot = record
|
|
potPrim,
|
|
potMax :LongWord;
|
|
end;
|
|
|
|
tprimeFac = record
|
|
pfPrims : array[1..10] of tPot;
|
|
pfCnt,
|
|
pfNum : LongWord;
|
|
end;
|
|
tSmallPrimes = array[0..6541] of longWord;
|
|
|
|
var
|
|
SmallPrimes: tSmallPrimes;
|
|
|
|
procedure InitSmallPrimes;
|
|
var
|
|
pr,testPr,j,maxprimidx: Longword;
|
|
isPrime : boolean;
|
|
Begin
|
|
maxprimidx := 0;
|
|
SmallPrimes[0] := 2;
|
|
pr := 3;
|
|
repeat
|
|
isprime := true;
|
|
j := 0;
|
|
repeat
|
|
testPr := SmallPrimes[j];
|
|
IF testPr*testPr > pr then
|
|
break;
|
|
If pr mod testPr = 0 then
|
|
Begin
|
|
isprime := false;
|
|
break;
|
|
end;
|
|
inc(j);
|
|
until false;
|
|
|
|
if isprime then
|
|
Begin
|
|
inc(maxprimidx);
|
|
SmallPrimes[maxprimidx]:= pr;
|
|
end;
|
|
inc(pr,2);
|
|
until pr > 1 shl 16 -1;
|
|
end;
|
|
|
|
procedure PrimeFacOut(primeDecomp:tprimeFac);
|
|
var
|
|
i : LongWord;
|
|
begin
|
|
with primeDecomp do
|
|
Begin
|
|
write(pfNum,' = ');
|
|
For i := 1 to pfCnt-1 do
|
|
with pfPrims[i] do
|
|
If potMax = 1 then
|
|
write(potPrim,'*')
|
|
else
|
|
write(potPrim,'^',potMax,'*');
|
|
with pfPrims[pfCnt] do
|
|
If potMax = 1 then
|
|
write(potPrim)
|
|
else
|
|
write(potPrim,'^',potMax);
|
|
end;
|
|
end;
|
|
|
|
procedure PrimeDecomposition(n:LongWord;var res:tprimeFac);
|
|
var
|
|
i,pr,cnt,quot{to minimize divisions} : LongWord;
|
|
Begin
|
|
res.pfNum := n;
|
|
res.pfCnt:= 0;
|
|
i := 0;
|
|
cnt := 0;
|
|
repeat
|
|
pr := SmallPrimes[i];
|
|
IF pr*pr>n then
|
|
Break;
|
|
|
|
quot := n div pr;
|
|
IF pr*quot = n then
|
|
with res do
|
|
Begin
|
|
inc(pfCnt);
|
|
with pfPrims[pfCnt] do
|
|
Begin
|
|
potPrim := pr;
|
|
potMax := 0;
|
|
repeat
|
|
n := quot;
|
|
quot := quot div pr;
|
|
inc(potMax);
|
|
until pr*quot <> n;
|
|
end;
|
|
end;
|
|
inc(i);
|
|
until false;
|
|
//a big prime left over?
|
|
IF n <> 1 then
|
|
with res do
|
|
Begin
|
|
inc(pfCnt);
|
|
with pfPrims[pfCnt] do
|
|
Begin
|
|
potPrim := n;
|
|
potMax := 1;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function CntProperDivs(const primeDecomp:tprimeFac):LongWord;
|
|
//count of proper divisors
|
|
var
|
|
i: LongWord;
|
|
begin
|
|
result := 1;
|
|
with primeDecomp do
|
|
For i := 1 to pfCnt do
|
|
result := result*(pfPrims[i].potMax+1);
|
|
//remove
|
|
dec(result);
|
|
end;
|
|
|
|
function findProperdivs(n:LongWord;var res:TRes):LongWord;
|
|
//simple trial division to get a sorted list of all proper divisors
|
|
var
|
|
i,j: LongWord;
|
|
Begin
|
|
result := 0;
|
|
i := 1;
|
|
j := n;
|
|
while j>i do
|
|
begin
|
|
j := n DIV i;
|
|
IF i*j = n then
|
|
Begin
|
|
//smaller factor part at the beginning upwards
|
|
res[result]:= i;
|
|
IF i <> j then
|
|
//bigger factor at the end downwards
|
|
res[MAXPROPERDIVS-result]:= j
|
|
else
|
|
//n is square number
|
|
res[MAXPROPERDIVS-result]:= 0;
|
|
inc(result);
|
|
end;
|
|
inc(i);
|
|
end;
|
|
|
|
If result>0 then
|
|
Begin
|
|
//move close together
|
|
i := result;
|
|
j := MAXPROPERDIVS-result+1;
|
|
result := 2*result-1;
|
|
repeat
|
|
res[i] := res[j];
|
|
inc(j);
|
|
inc(i);
|
|
until i > result;
|
|
|
|
if res[result-1] = 0 then
|
|
dec(result);
|
|
end;
|
|
end;
|
|
|
|
procedure AllFacsOut(n: Longword);
|
|
var
|
|
res:TRes;
|
|
i,k,j:LongInt;
|
|
Begin
|
|
j := findProperdivs(n,res);
|
|
write(n:5,' : ');
|
|
For k := 0 to j-2 do write(res[k],',');
|
|
IF j>=1 then
|
|
write(res[j-1]);
|
|
writeln;
|
|
end;
|
|
|
|
var
|
|
primeDecomp: tprimeFac;
|
|
rs : tRes;
|
|
i,j,max,maxcnt: LongWord;
|
|
BEGIN
|
|
InitSmallPrimes;
|
|
For i := 1 to 10 do
|
|
AllFacsOut(i);
|
|
writeln;
|
|
max := 0;
|
|
maxCnt := 0;
|
|
For i := 1 to 20*1000 do
|
|
Begin
|
|
PrimeDecomposition(i,primeDecomp);
|
|
j := CntProperDivs(primeDecomp);
|
|
IF j> maxCnt then
|
|
Begin
|
|
maxcnt := j;
|
|
max := i;
|
|
end;
|
|
end;
|
|
PrimeDecomposition(max,primeDecomp);
|
|
j := CntProperDivs(primeDecomp);
|
|
|
|
PrimeFacOut(primeDecomp);writeln(' ',j:10,' factors'); writeln;
|
|
//https://en.wikipedia.org/wiki/Highly_composite_number <= HCN
|
|
//http://wwwhomes.uni-bielefeld.de/achim/highly.txt the first 1200 HCN
|
|
max := 3491888400;
|
|
PrimeDecomposition(max,primeDecomp);
|
|
j := CntProperDivs(primeDecomp);
|
|
PrimeFacOut(primeDecomp);writeln(' ',j:10,' factors'); writeln;
|
|
END.
|