-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathsmallest_lucas-carmichael_divisible_by_n.pl
More file actions
103 lines (73 loc) · 2.65 KB
/
smallest_lucas-carmichael_divisible_by_n.pl
File metadata and controls
103 lines (73 loc) · 2.65 KB
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
91
92
93
94
95
96
97
98
99
100
101
102
103
#!/usr/bin/perl
# Method for finding the smallest Lucas-Carmichael number divisible by n.
# See also:
# https://oeis.org/A253597
# https://oeis.org/A253598
use 5.036;
use ntheory 0.74 qw(:all);
sub lucas_carmichael_from_multiple ($A, $B, $m, $L, $lo, $k, $callback) {
my $hi = vecmin(rootint(divint($B, $m), $k), sqrtint($B));
if ($lo > $hi) {
return;
}
if ($k == 1) {
$lo = vecmax($lo, cdivint($A, $m));
$lo > $hi && return;
my $t = mulmod(invmod($m, $L) // (return), -1, $L);
$t > $hi && return;
$t += $L * cdivint($lo - $t, $L) if ($t < $lo);
for (my $p = $t ; $p <= $hi ; $p += $L) {
if ($m % $p != 0 and is_prime($p)) {
my $n = $m * $p;
if (($n + 1) % ($p + 1) == 0) {
$callback->($n);
}
}
}
return;
}
foreach my $p (@{primes($lo, $hi)}) {
$m % $p == 0 and next;
gcd($m, $p + 1) == 1 or next;
__SUB__->($A, $B, $m * $p, lcm($L, $p + 1), $p + 1, $k - 1, $callback);
}
}
sub lucas_carmichael_divisible_by ($m) {
$m >= 1 or return;
$m % 2 == 0 and return;
is_square_free($m) || return;
gcd($m, divisor_sum($m)) == 1 or return;
my $A = vecmax(399, $m);
my $B = 2 * $A;
my $L = vecmax(1, lcm(map { $_ + 1 } factor($m)));
my @found;
for (; ;) {
for my $k ((is_prime($m) ? 2 : 1) .. 1000) {
my @P;
for (my $p = 3 ; scalar(@P) < $k ; $p = next_prime($p)) {
if ($m % $p != 0 and $L % $p != 0) {
push @P, $p;
}
}
last if (vecprod(@P, $m) > $B);
my $callback = sub ($n) {
push @found, $n;
$B = vecmin($B, $n);
};
lucas_carmichael_from_multiple($A, $B, $m, $L, $P[0], $k, $callback);
}
last if @found;
$A = $B + 1;
$B = 2 * $A;
}
vecmin(@found);
}
lucas_carmichael_divisible_by(1) == 399 or die;
lucas_carmichael_divisible_by(3) == 399 or die;
lucas_carmichael_divisible_by(3 * 7) == 399 or die;
lucas_carmichael_divisible_by(7 * 19) == 399 or die;
say join(', ', map { lucas_carmichael_divisible_by($_) } @{primes(3, 50)});
say join(', ', map { lucas_carmichael_divisible_by($_) } 1 .. 100);
__END__
399, 935, 399, 935, 2015, 935, 399, 4991, 51359, 2015, 1584599, 20705, 5719, 18095
399, 399, 935, 399, 935, 2015, 935, 399, 399, 4991, 51359, 2015, 8855, 1584599, 9486399, 20705, 5719, 18095, 2915, 935, 399, 46079, 162687, 2015, 22847, 46079, 16719263, 8855, 12719, 7055, 935, 80189, 189099039, 104663