Chernick's Carmichael numbers
In 1939, Jack Chernick proved that, for n ≥ 3 and m ≥ 1:
U(n, m) = (6m + 1) * (12m + 1) * Product_{i=1..n-2} (2^i * 9m + 1)
is a Carmichael number if all the factors are primes and, for n > 4, m is a multiple of 2^(n-4).
- Example
U(3, m) = (6m + 1) * (12m + 1) * (18m + 1) U(4, m) = U(3, m) * (2^2 * 9m + 1) U(5, m) = U(4, m) * (2^3 * 9m + 1) ... U(n, m) = U(n-1, m) * (2^(n-2) * 9m + 1)
- The smallest Chernick's Carmichael number with 3 prime factors, is: U(3, 1) = 1729.
- The smallest Chernick's Carmichael number with 4 prime factors, is: U(4, 1) = 63973.
- The smallest Chernick's Carmichael number with 5 prime factors, is: U(5, 380) = 26641259752490421121.
For n = 5, the smallest number m that satisfy Chernick's conditions, is m = 380, therefore U(5, 380) is the smallest Chernick's Carmichael number with 5 prime factors.
U(5, 380) is a Chernick's Carmichael number because m = 380 is a multiple of 2^(n-4), where n = 5, and the factors { (6*380 + 1), (12*380 + 1), (18*380 + 1), (36*380 + 1), (72*380 + 1) } are all prime numbers.
- Task
For n ≥ 3, let a(n) be the smallest Chernick's Carmichael number with n prime factors.
- Compute a(n) for n = 3..9.
- Optional: find a(10).
Note: it's perfectly acceptable to show the terms in factorized form:
a(3) = 7 * 13 * 19 a(4) = 7 * 13 * 19 * 37 a(5) = 2281 * 4561 * 6841 * 13681 * 27361 ...
- See also
- Related tasks
C++
<lang cpp>#include <gmp.h>
- include <iostream>
using namespace std;
typedef unsigned long long int u64;
bool primality_pretest(u64 k) { // for k > 23
if (!(k % 3) || !(k % 5) || !(k % 7) || !(k % 11) || !(k % 13) || !(k % 17) || !(k % 19) || !(k % 23) ) { return (k <= 23); }
return true;
}
bool probprime(u64 k, mpz_t n) {
mpz_set_ui(n, k); return mpz_probab_prime_p(n, 0);
}
bool is_chernick(int n, u64 m, mpz_t z) {
if (!primality_pretest(6 * m + 1)) { return false; }
if (!primality_pretest(12 * m + 1)) { return false; }
u64 t = 9 * m;
for (int i = 1; i <= n - 2; i++) { if (!primality_pretest((t << i) + 1)) { return false; } }
if (!probprime(6 * m + 1, z)) { return false; }
if (!probprime(12 * m + 1, z)) { return false; }
for (int i = 1; i <= n - 2; i++) { if (!probprime((t << i) + 1, z)) { return false; } }
return true;
}
int main() {
mpz_t z; mpz_inits(z, NULL);
for (int n = 3; n <= 10; n++) {
// `m` is a multiple of 2^(n-4), for n > 4 u64 multiplier = (n > 4) ? (1 << (n - 4)) : 1;
// For n > 5, m is also a multiple of 5 if (n > 5) { multiplier *= 5; }
for (u64 k = 1; ; k++) {
u64 m = k * multiplier;
if (is_chernick(n, m, z)) { cout << "a(" << n << ") has m = " << m << endl; break; } } }
return 0;
}</lang>
- Output:
a(3) has m = 1 a(4) has m = 1 a(5) has m = 380 a(6) has m = 380 a(7) has m = 780320 a(8) has m = 950560 a(9) has m = 950560 a(10) has m = 3208386195840
(takes ~3.5 minutes)
F#
This task uses Extensible Prime Generator (F#) <lang fsharp> // Generate Chernick's Carmichael numbers. Nigel Galloway: June 1st., 2019 let fMk m k=isPrime(6*m+1) && isPrime(12*m+1) && [1..k-2]|>List.forall(fun n->isPrime(9*(pown 2 n)*m+1)) let fX k=Seq.initInfinite(fun n->(n+1)*(pown 2 (k-4))) |> Seq.filter(fun n->fMk n k ) let cherCar k=let m=Seq.head(fX k) in printfn "m=%d primes -> %A " m ([6*m+1;12*m+1]@List.init(k-2)(fun n->9*(pown 2 (n+1))*m+1)) [4..9] |> Seq.iter cherCar </lang>
- Output:
cherCar(4): m=1 primes -> [7; 13; 19; 37] cherCar(5): m=380 primes -> [2281; 4561; 6841; 13681; 27361] cherCar(6): m=380 primes -> [2281; 4561; 6841; 13681; 27361; 54721] cherCar(7): m=780320 primes -> [4681921; 9363841; 14045761; 28091521; 56183041; 112366081; 224732161] cherCar(8): m=950560 primes -> [5703361; 11406721; 17110081; 34220161; 68440321; 136880641; 273761281; 547522561] cherCar(9): m=950560 primes -> [5703361; 11406721; 17110081; 34220161; 68440321; 136880641; 273761281; 547522561; 1095045121]
Go
<lang go>package main
import (
"fmt" "math/big"
)
var (
zero = new(big.Int) prod = new(big.Int) fact = new(big.Int)
)
func ccFactors(n, m uint64) (*big.Int, bool) {
prod.SetUint64(6*m + 1) if !prod.ProbablyPrime(0) { return zero, false } fact.SetUint64(12*m + 1) if !fact.ProbablyPrime(0) { // 100% accurate up to 2 ^ 64 return zero, false } prod.Mul(prod, fact) for i := uint64(1); i <= n-2; i++ { fact.SetUint64((1<<i)*9*m + 1) if !fact.ProbablyPrime(0) { return zero, false } prod.Mul(prod, fact) } return prod, true
}
func ccNumbers(start, end uint64) {
for n := start; n <= end; n++ { m := uint64(1) if n > 4 { m = 1 << (n - 4) } for { num, ok := ccFactors(n, m) if ok { fmt.Printf("a(%d) = %d\n", n, num) break } if n <= 4 { m++ } else { m += 1 << (n - 4) } } }
}
func main() {
ccNumbers(3, 9)
}</lang>
- Output:
a(3) = 1729 a(4) = 63973 a(5) = 26641259752490421121 a(6) = 1457836374916028334162241 a(7) = 24541683183872873851606952966798288052977151461406721 a(8) = 53487697914261966820654105730041031613370337776541835775672321 a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841
PARI/GP
Just The Impossible
As I've said before a day isn't worth living unless I've done the impossible before breakfast! If before breakfast means starting last night and seeing what happened when I get up then this qualifies. See the discussion page. <lang parigp> n=0 ? until(isprime(6*n+1)&isprime(12*n+1)&isprime(18*n+1)&isprime(36*n+1)&isprime(72*n+1)&isprime(144*n+1)&isprime(288*n+1)&isprime(576*n+1)&isprime(1152*n+1)&isprime(2304*n+1),n=n+ print(n) </lang>
- Output:
3208386195840
Perl
<lang perl>use 5.020; use warnings; use ntheory qw/:all/; use experimental qw/signatures/;
sub chernick_carmichael_factors ($n, $m) {
(6*$m + 1, 12*$m + 1, (map { (1 << $_) * 9*$m + 1 } 1 .. $n-2));
}
sub chernick_carmichael_number ($n, $callback) {
my $multiplier = ($n > 4) ? (1 << ($n-4)) : 1;
for (my $m = 1 ; ; ++$m) { my @f = chernick_carmichael_factors($n, $m * $multiplier); next if not vecall { is_prime($_) } @f; $callback->(@f); last; }
}
foreach my $n (3..9) {
chernick_carmichael_number($n, sub (@f) { say "a($n) = ", vecprod(@f) });
}</lang>
- Output:
a(3) = 1729 a(4) = 63973 a(5) = 26641259752490421121 a(6) = 1457836374916028334162241 a(7) = 24541683183872873851606952966798288052977151461406721 a(8) = 53487697914261966820654105730041031613370337776541835775672321 a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841
Perl 6
Use the ntheory library from Perl 5 for primality testing since it is much, much faster than Perl 6s built-in .is-prime method.
<lang perl6>use Inline::Perl5; use ntheory:from<Perl5> <:all>;
sub chernick-carmichael-factors ($n, $m) {
6*$m + 1, 12*$m + 1, |((1 .. $n-2).map: { (1 +< $_) * 9*$m + 1 } )
}
sub chernick-carmichael-number ($n) {
my $multiplier = 1; my $iterator = 1 .. *;
if $n > 4 { $multiplier = 1 +< ($n-4); $iterator = (1..*).map: * * 5; }
my $i = $iterator.first: -> $m { [&&] chernick-carmichael-factors($n, $m * $multiplier).map: { is_prime($_) #`[ .is-prime ] } }
chernick-carmichael-factors($n, $i * $multiplier)
}
for 3 .. 9 -> $n {
my @f = chernick-carmichael-number($n); say "a($n): {[*] @f} = {@f.join(' ⨉ ')}";
}</lang>
- Output:
a(3): 1729 = 7 ⨉ 13 ⨉ 19 a(4): 63973 = 7 ⨉ 13 ⨉ 19 ⨉ 37 a(5): 26641259752490421121 = 2281 ⨉ 4561 ⨉ 6841 ⨉ 13681 ⨉ 27361 a(6): 1457836374916028334162241 = 2281 ⨉ 4561 ⨉ 6841 ⨉ 13681 ⨉ 27361 ⨉ 54721 a(7): 24541683183872873851606952966798288052977151461406721 = 4681921 ⨉ 9363841 ⨉ 14045761 ⨉ 28091521 ⨉ 56183041 ⨉ 112366081 ⨉ 224732161 a(8): 53487697914261966820654105730041031613370337776541835775672321 = 5703361 ⨉ 11406721 ⨉ 17110081 ⨉ 34220161 ⨉ 68440321 ⨉ 136880641 ⨉ 273761281 ⨉ 547522561 a(9): 58571442634534443082821160508299574798027946748324125518533225605795841 = 5703361 ⨉ 11406721 ⨉ 17110081 ⨉ 34220161 ⨉ 68440321 ⨉ 136880641 ⨉ 273761281 ⨉ 547522561 ⨉ 1095045121
Sidef
<lang ruby>func chernick_carmichael_factors (n, m) {
[6*m + 1, 12*m + 1, {|i| 2**i * 9*m + 1 }.map(1 .. n-2)...]
}
func is_chernick_carmichael (n, m) {
(n == 2) ? (is_prime(6*m + 1) && is_prime(12*m + 1)) : (is_prime(2**(n-2) * 9*m + 1) && __FUNC__(n-1, m))
}
func chernick_carmichael_number(n, callback) {
var multiplier = (n>4 ? 2**(n-4) : 1) var m = (1..Inf -> first {|m| is_chernick_carmichael(n, m * multiplier) }) var f = chernick_carmichael_factors(n, m * multiplier) callback(f...)
}
for n in (3..9) {
chernick_carmichael_number(n, {|*f| say "a(#{n}) = #{f.join(' * ')}" })
}</lang>
- Output:
a(3) = 7 * 13 * 19 a(4) = 7 * 13 * 19 * 37 a(5) = 2281 * 4561 * 6841 * 13681 * 27361 a(6) = 2281 * 4561 * 6841 * 13681 * 27361 * 54721 a(7) = 4681921 * 9363841 * 14045761 * 28091521 * 56183041 * 112366081 * 224732161 a(8) = 5703361 * 11406721 * 17110081 * 34220161 * 68440321 * 136880641 * 273761281 * 547522561 a(9) = 5703361 * 11406721 * 17110081 * 34220161 * 68440321 * 136880641 * 273761281 * 547522561 * 1095045121
zkl
GNU Multiple Precision Arithmetic Library
Using GMP (probabilistic primes), because it is easy and fast to check primeness. <lang zkl>var [const] BI=Import("zklBigNum"); // libGMP
fcn ccFactors(n,m){ // not re-entrant
prod:=BI(6*m + 1); if(not prod.probablyPrime()) return(False); fact:=BI(12*m + 1); if(not fact.probablyPrime()) return(False); prod.mul(fact); foreach i in ([1..n-2]){ fact.set((2).pow(i) *9*m + 1); if(not fact.probablyPrime()) return(False); prod.mul(fact); } prod
}
fcn ccNumbers(start,end){
foreach n in ([start..end]){ a,m := ( if(n<=4) 1 else (2).pow(n - 4) ), a; while(1){
if(num := ccFactors(n,m)){ println("a(%d) = %,d".fmt(n,num)); break; } m+=a;
} }
}</lang> <lang zkl>ccNumbers(3,9);</lang>
- Output:
a(3) = 1,729 a(4) = 63,973 a(5) = 26,641,259,752,490,421,121 a(6) = 1,457,836,374,916,028,334,162,241 a(7) = 24,541,683,183,872,873,851,606,952,966,798,288,052,977,151,461,406,721 a(8) = 53,487,697,914,261,966,820,654,105,730,041,031,613,370,337,776,541,835,775,672,321 a(9) = 58,571,442,634,534,443,082,821,160,508,299,574,798,027,946,748,324,125,518,533,225,605,795,841