-
Notifications
You must be signed in to change notification settings - Fork 34
/
Copy pathlucas-carmichael_numbers_in_range.pl
90 lines (63 loc) · 3.86 KB
/
lucas-carmichael_numbers_in_range.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/perl
# Daniel "Trizen" Șuteu
# Date: 27 August 2022
# https://github.com/trizen
# Generate all the Lucas-Carmichael numbers with n prime factors in a given range [a,b]. (not in sorted order)
# See also:
# https://en.wikipedia.org/wiki/Almost_prime
# https://trizenx.blogspot.com/2020/08/pseudoprimes-construction-methods-and.html
# PARI/GP program (in range [A,B]) (simple):
# lucas_carmichael(A, B, k) = A=max(A, vecprod(primes(k+1))\2); (f(m, l, lo, k) = my(list=List()); my(hi=sqrtnint(B\m, k)); if(lo > hi, return(list)); if(k==1, forprime(p=max(lo, ceil(A/m)), hi, my(t=m*p); if((t+1)%l == 0 && (t+1)%(p+1) == 0, listput(list, t))), forprime(p=lo, hi, if(gcd(m, p+1) == 1, list=concat(list, f(m*p, lcm(l, p+1), p+1, k-1))))); list); vecsort(Vec(f(1, 1, 3, k)));
# PARI/GP program (in range [A, B]) (fast):
# lucas_carmichael(A, B, k) = A=max(A, vecprod(primes(k+1))\2); my(max_p=sqrtint(B+1)-1); (f(m, l, lo, k) = my(list=List()); my(hi=min(max_p, sqrtnint(B\m, k))); if(lo > hi, return(list)); if(k==1, lo=max(lo, ceil(A/m)); my(t=lift(-1/Mod(m,l))); while(t < lo, t += l); forstep(p=t, hi, l, if(isprime(p), my(n=m*p); if((n+1)%(p+1) == 0, listput(list, n)))), forprime(p=lo, hi, if(gcd(m, p+1) == 1, list=concat(list, f(m*p, lcm(l, p+1), p+1, k-1))))); list); vecsort(Vec(f(1, 1, 3, k)));
# PARI/GP program to generate all the Lucas-Carmichael numbers <= n (fast):
# lucas_carmichael(A, B, k) = A=max(A, vecprod(primes(k+1))\2); my(max_p=sqrtint(B+1)-1); (f(m, l, lo, k) = my(list=List()); my(hi=min(max_p, sqrtnint(B\m, k))); if(lo > hi, return(list)); if(k==1, lo=max(lo, ceil(A/m)); my(t=lift(-1/Mod(m,l))); while(t < lo, t += l); forstep(p=t, hi, l, if(isprime(p), my(n=m*p); if((n+1)%(p+1) == 0, listput(list, n)))), forprime(p=lo, hi, if(gcd(m, p+1) == 1, list=concat(list, f(m*p, lcm(l, p+1), p+1, k-1))))); list); f(1, 1, 3, k);
# upto(n) = my(list=List()); for(k=3, oo, if(vecprod(primes(k+1))\2 > n, break); list=concat(list, lucas_carmichael(1, n, k))); vecsort(Vec(list));
use 5.020;
use warnings;
use ntheory qw(:all);
use experimental qw(signatures);
sub divceil ($x, $y) { # ceil(x/y)
(($x % $y == 0) ? 0 : 1) + divint($x, $y);
}
sub lucas_carmichael_numbers_in_range ($A, $B, $k) {
$A = vecmax($A, pn_primorial($k));
# Largest possisble prime factor for Lucas-Carmichael numbers <= B
my $max_p = sqrtint($B);
my @list;
sub ($m, $L, $lo, $k) {
my $hi = rootint(divint($B, $m), $k);
if ($lo > $hi) {
return;
}
if ($k == 1) {
$hi = $max_p if ($hi > $max_p);
$lo = vecmax($lo, divceil($A, $m));
$lo > $hi && return;
my $t = $L - invmod($m, $L);
$t > $hi && return;
$t += $L * divceil($lo - $t, $L) if ($t < $lo);
for (my $p = $t ; $p <= $hi ; $p += $L) {
if (($m * $p + 1) % ($p + 1) == 0 and is_prime($p)) {
push @list, $m * $p;
}
}
return;
}
foreach my $p (@{primes($lo, $hi)}) {
if (gcd($m, $p + 1) == 1) {
__SUB__->($m * $p, lcm($L, $p + 1), $p + 1, $k - 1);
}
}
}
->(1, 1, 3, $k);
return sort { $a <=> $b } @list;
}
# Generate all the Lucas-Carmichael numbers with 5 prime factors in the range [100, 10^8]
my $k = 5;
my $from = 100;
my $upto = 1e8;
my @arr = lucas_carmichael_numbers_in_range($from, $upto, $k);
say join(', ', @arr);
__END__
588455, 1010735, 2276351, 2756159, 4107455, 4874639, 5669279, 6539819, 8421335, 13670855, 16184663, 16868159, 21408695, 23176439, 24685199, 25111295, 26636687, 30071327, 34347599, 34541639, 36149399, 36485015, 38999519, 39715319, 42624911, 43134959, 49412285, 49591919, 54408959, 54958799, 57872555, 57953951, 64456223, 66709019, 73019135, 77350559, 78402815, 82144799, 83618639, 86450399, 93277079, 96080039, 98803439