Jump to content

Chernick's Carmichael numbers

From Rosetta Code
Task
Chernick's Carmichael numbers
You are encouraged to solve this task according to the task description, using any language you may know.

In 1939, Jack Chernick proved that, for and :

   

is a Carmichael number if all the factors are primes and, for , is a multiple of .


Example
   
   
   
   
   
  • 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



Translation of: Go
Works with: ALGOL 68G version Any - tested with release 3.5.9 Win32 and 2.8.3.win32

Uses ALGOL 68 Genie's LONG LONG INT which has programmer specifiable precision.

Note the RC ALGOL 68-primes library is on a separate page on Rosetta Code, see the above link.

BEGIN # find some of Chernick's Carmichael numbers - translation of Go       #

    PR precision 80 PR                  # set the precision of LONG LONG INT #
    PR read "primes.incl.a68" PR                   # include prime utilities #

    # integer mode large enough to hold a Chernick's Carmichael number       #
    MODE CHERNICKINTEGER = LONG LONG INT;
    # integer mode large to hold a factor of a Chernick's Carmichael number  #
    MODE CHERNICKFACTOR  = LONG INT;

    # returns the value of the Chernick's Carmichaal number U( n, m )        #
    #      or 0 if n and m are not a Chernicj's Carmichael number            #
    PROC possible chernick = ( INT n, m )CHERNICKINTEGER:
         IF   CHERNICKINTEGER prod := 6 * m + 1;
              NOT  is probably prime( prod )
         THEN 0
         ELIF CHERNICKFACTOR f := 12 * m + 1;
              NOT  is probably prime( f )
         THEN 0
         ELSE CHERNICKFACTOR t := 9 * m;
              prod *:= f;
              f     := t;
              BOOL result := TRUE;
              CHERNICKINTEGER ii := 1;
              WHILE IF   ii > n - 2
                    THEN FALSE
                    ELSE f      := ( t +:= t ) + 1;
                         result := is probably prime( f )
                    FI
              DO    ii   +:= 1;
                    prod *:= f
              OD;
              IF result THEN prod ELSE 0 FI
         FI # possible chernick # ;

    BEGIN
        FOR n FROM 3 TO 9 DO
            INT m := IF n > 4 THEN 2 ^ ( n - 4 ) ELSE 1 FI;
            WHILE IF   CHERNICKINTEGER cn = possible chernick( n, m );
                       cn > 0
                  THEN print( ( "U( ",   whole(  n,  0 ) ) );
                       print( ( ", "  ,  whole(  m, -8 ) ) );
                       print( ( " ): ",  whole( cn,  0 ), newline ) );
                       FALSE
                  ELSE m +:= IF n <= 4 THEN 1 ELSE 2 ^ ( n - 4 ) FI;
                       TRUE
                  FI
            DO SKIP OD
        OD
    END
END
Output:
U( 3,        1 ): 1729
U( 4,        1 ): 63973
U( 5,      380 ): 26641259752490421121
U( 6,      380 ): 1457836374916028334162241
U( 7,   780320 ): 24541683183872873851606952966798288052977151461406721
U( 8,   950560 ): 53487697914261966820654105730041031613370337776541835775672321
U( 9,   950560 ): 58571442634534443082821160508299574798027946748324125518533225605795841

C

Library: GMP
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>

typedef unsigned long long int u64;

#define TRUE 1
#define FALSE 0

int primality_pretest(u64 k) {
    if (!(k %  3) || !(k %  5) || !(k %  7) || !(k % 11) || !(k % 13) || !(k % 17) || !(k % 19) || !(k % 23)) return (k <= 23);
    return TRUE;
}

int probprime(u64 k, mpz_t n) {
    mpz_set_ui(n, k);
    return mpz_probab_prime_p(n, 0);
}

int is_chernick(int n, u64 m, mpz_t z) {
    u64 t = 9 * m;
    if (primality_pretest(6 * m + 1) == FALSE) return FALSE;
    if (primality_pretest(12 * m + 1) == FALSE) return FALSE;
    for (int i = 1; i <= n - 2; i++) if (primality_pretest((t << i) + 1) == FALSE) return FALSE;
    if (probprime(6 * m + 1, z) == FALSE) return FALSE;
    if (probprime(12 * m + 1, z) == FALSE) return FALSE;
    for (int i = 1; i <= n - 2; i++) if (probprime((t << i) + 1, z) == FALSE) return FALSE;
    return TRUE;
}

int main(int argc, char const *argv[]) {
    mpz_t z;
    mpz_inits(z, NULL);

    for (int n = 3; n <= 10; n ++) {
        u64 multiplier = (n > 4) ? (1 << (n - 4)) : 1;

        if (n > 5) multiplier *= 5;

        for (u64 k = 1; ; k++) {
            u64 m = k * multiplier;

            if (is_chernick(n, m, z) == TRUE) {
                printf("a(%d) has m = %llu\n", n, m);
                break;
            }
        }
    }

    return 0;
}
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
Library: GMP
#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;
}
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)

// Generate Chernick's Carmichael numbers. Nigel Galloway: June 1st., 2019
open Open.Numeric.Primes
let fMk m k=Number.IsPrime(6UL*m+1UL) && Number.IsPrime(12UL*m+1UL) && [1..k-2]|>List.forall(fun n->Number.IsPrime(9UL*(pown 2UL n)*m+1UL))
let fX k=Seq.initInfinite(fun n->match k with 3->uint64(n+1) |_->uint64(n+1)*(pown 2UL (k-4)))|>Seq.filter(fun n->fMk n k)
let cherCar k=let m=Seq.head(fX k) in sprintf "m=%d primes-> %A " m ([6UL*m+1UL;12UL*m+1UL]@List.init(k-2)(fun n->9UL*(pown 2UL (n+1))*m+1UL))
[3..9] |> Seq.iter(fun g->printfn $"cherCar %d{g}: %s{cherCar g}")
Output:
cherCar 3: m=1 primes-> [7; 13; 19]
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]

Basic only

#include "isprime.bas"

Function PrimalityPretest(k As Integer) As Boolean
    Dim As Integer ppp(1 To 8) = {3,5,7,11,13,17,19,23}
    For i As Integer = 1 To Ubound(ppp)
        If k Mod ppp(i) = 0 Then Return (k <= 23)
    Next i
    Return True
End Function

Function isChernick(n As Integer, m As Integer) As Boolean
    Dim As Integer i, t = 9 * m
    
    If Not PrimalityPretest(6 * m + 1) Then Return False
    If Not PrimalityPretest(12 * m + 1) Then Return False
    
    For i = 1 To n-1
        If Not PrimalityPretest(t * (2 ^ i) + 1) Then Return False
    Next i
    
    If Not isPrime(6 * m + 1) Then Return False
    If Not isPrime(12 * m + 1) Then Return False
    
    For i = 1 To n - 2
        If Not isPrime(t * (2 ^ i) + 1) Then Return False
    Next i
    Return True
End Function

Dim As Uinteger multiplier, k, m = 1
For n As Integer = 3 To 9
    multiplier = Iif (n > 4, 2 ^ (n-4), 1)
    If n > 5 Then multiplier *= 5
    
    k = 1
    Do
        m = k * multiplier
        If isChernick(n, m) Then
            Print "a(" & n & ") has m = " & m
            Exit Do
        End If
        k += 1
    Loop
Next n
Sleep

Basic only

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)
}
Output:
a(3) = 1729
a(4) = 63973
a(5) = 26641259752490421121
a(6) = 1457836374916028334162241
a(7) = 24541683183872873851606952966798288052977151461406721
a(8) = 53487697914261966820654105730041031613370337776541835775672321
a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841

Basic plus optional


To reach a(10) in a reasonable time, a much more efficient approach is needed.

The following version takes account of the optimizations referred to in the Talk page and previewed in the C++ entry above.

It also uses a wrapper for the C library, GMP, which despite the overhead of cgo is still much faster than Go's native big.Int library.

The resulting executable is several hundred times faster than before and, even on my modest Celeron @1.6GHZ, reaches a(9) in under 10ms and a(10) in about 22 minutes.

package main

import (
    "fmt"
    big "github.com/ncw/gmp"
)

const (
    min = 3
    max = 10
)

var (
    prod       = new(big.Int)
    fact       = new(big.Int)
    factors    = [max]uint64{}
    bigFactors = [max]*big.Int{}
)

func init() {
    for i := 0; i < max; i++ {
        bigFactors[i] = big.NewInt(0)
    }
}

func isPrimePretest(k uint64) bool {
    if k%3 == 0 || k%5 == 0 || k%7 == 0 || k%11 == 0 ||
        k%13 == 0 || k%17 == 0 || k%19 == 0 || k%23 == 0 {
        return k <= 23
    }
    return true
}

func ccFactors(n, m uint64) bool {
    if !isPrimePretest(6*m + 1) {
        return false
    }
    if !isPrimePretest(12*m + 1) {
        return false
    }
    factors[0] = 6*m + 1
    factors[1] = 12*m + 1
    t := 9 * m
    for i := uint64(1); i <= n-2; i++ {
        tt := (t << i) + 1
        if !isPrimePretest(tt) {
            return false
        }
        factors[i+1] = tt
    }

    for i := 0; i < int(n); i++ {
        fact.SetUint64(factors[i])
        if !fact.ProbablyPrime(0) {
            return false
        }
        bigFactors[i].Set(fact)
    }
    return true
}

func prodFactors(n uint64) *big.Int {
    prod.Set(bigFactors[0])
    for i := 1; i < int(n); i++ {
        prod.Mul(prod, bigFactors[i])
    }
    return prod
}

func ccNumbers(start, end uint64) {
    for n := start; n <= end; n++ {
        mult := uint64(1)
        if n > 4 {
            mult = 1 << (n - 4)
        }
        if n > 5 {
            mult *= 5
        }
        m := mult
        for {
            if ccFactors(n, m) {
                num := prodFactors(n)
                fmt.Printf("a(%d) = %d\n", n, num)
                fmt.Printf("m(%d) = %d\n", n, m)
                fmt.Println("Factors:", factors[:n], "\n")
                break
            }
            m += mult
        }
    }
}

func main() {
    ccNumbers(min, max)
}
Output:
a(3) = 1729
m(3) = 1
Factors: [7 13 19] 

a(4) = 63973
m(4) = 1
Factors: [7 13 19 37] 

a(5) = 26641259752490421121
m(5) = 380
Factors: [2281 4561 6841 13681 27361] 

a(6) = 1457836374916028334162241
m(6) = 380
Factors: [2281 4561 6841 13681 27361 54721] 

a(7) = 24541683183872873851606952966798288052977151461406721
m(7) = 780320
Factors: [4681921 9363841 14045761 28091521 56183041 112366081 224732161] 

a(8) = 53487697914261966820654105730041031613370337776541835775672321
m(8) = 950560
Factors: [5703361 11406721 17110081 34220161 68440321 136880641 273761281 547522561] 

a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841
m(9) = 950560
Factors: [5703361 11406721 17110081 34220161 68440321 136880641 273761281 547522561 1095045121] 

a(10) = 24616075028246330441656912428380582403261346369700917629170235674289719437963233744091978433592331048416482649086961226304033068172880278517841921
m(10) = 3208386195840
Factors: [19250317175041 38500634350081 57750951525121 115501903050241 231003806100481 462007612200961 924015224401921 1848030448803841 3696060897607681 7392121795215361] 

J

Brute force:

a=: {{)v
  if.3=y do.1729 return.end.
  m=. z=. 2^y-4
  f=. 6 12,9*2^}.i.y-1
  while.do.
    uf=.1+f*m
    if.*/1 p: uf do. */x:uf return.end.
    m=.m+z
  end.
}}

Task examples:

   a 3
1729
   a 4
63973
   a 5
26641259752490421121
   a 6
1457836374916028334162241
   a 7
24541683183872873851606952966798288052977151461406721
   a 8
53487697914261966820654105730041031613370337776541835775672321
   a 9
58571442634534443082821160508299574798027946748324125518533225605795841
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

public class ChernicksCarmichaelNumbers {

    public static void main(String[] args) {
        for ( long n = 3 ; n < 10 ; n++ ) {
            long m = 0;
            boolean foundComposite = true;
            List<Long> factors = null;
            while ( foundComposite ) {
                m += (n <= 4 ? 1 : (long) Math.pow(2, n-4) * 5);
                factors = U(n, m);
                foundComposite = false;
                for ( long factor : factors ) {
                    if ( ! isPrime(factor) ) {
                        foundComposite = true;
                        break;
                    }
                }
            }
            System.out.printf("U(%d, %d) = %s = %s %n", n, m, display(factors), multiply(factors));
        }
    }
    
    private static String display(List<Long> factors) {
        return factors.toString().replace("[", "").replace("]", "").replaceAll(", ", " * ");
    }
    
    private static BigInteger multiply(List<Long> factors) {
        BigInteger result = BigInteger.ONE;
        for ( long factor : factors ) {
            result = result.multiply(BigInteger.valueOf(factor));
        }
        return result;
    }
    
    private static List<Long> U(long n, long m) {
        List<Long> factors = new ArrayList<>();
        factors.add(6*m + 1);
        factors.add(12*m + 1);
        for ( int i = 1 ; i <= n-2 ; i++ ) {
            factors.add(((long)Math.pow(2, i)) * 9 * m + 1);
        }
        return factors;
    }

    private static final int MAX = 100_000;
    private static final boolean[] primes = new boolean[MAX];
    private static boolean SIEVE_COMPLETE = false;
    
    private static final boolean isPrimeTrivial(long test) {
        if ( ! SIEVE_COMPLETE ) {
            sieve();
            SIEVE_COMPLETE = true;
        }
        return primes[(int) test];
    }
    
    private static final void sieve() {
        //  primes
        for ( int i = 2 ; i < MAX ; i++ ) {
            primes[i] = true;            
        }
        for ( int i = 2 ; i < MAX ; i++ ) {
            if ( primes[i] ) {
                for ( int j = 2*i ; j < MAX ; j += i ) {
                    primes[j] = false;
                }
            }
        }
    }

    //  See http://primes.utm.edu/glossary/page.php?sort=StrongPRP
    public static final boolean isPrime(long testValue) {
        if ( testValue == 2 ) return true;
        if ( testValue % 2 == 0 ) return false;
        if ( testValue <= MAX ) return isPrimeTrivial(testValue);
        long d = testValue-1;
        int s = 0;
        while ( d % 2 == 0 ) {
            s += 1;
            d /= 2;
        }
        if ( testValue < 1373565L ) {
            if ( ! aSrp(2, s, d, testValue) ) {
                return false;
            }
            if ( ! aSrp(3, s, d, testValue) ) {
                return false;
            }
            return true;
        }
        if ( testValue < 4759123141L ) {
            if ( ! aSrp(2, s, d, testValue) ) {
                return false;
            }
            if ( ! aSrp(7, s, d, testValue) ) {
                return false;
            }
            if ( ! aSrp(61, s, d, testValue) ) {
                return false;
            }
            return true;
        }
        if ( testValue < 10000000000000000L ) {
            if ( ! aSrp(3, s, d, testValue) ) {
                return false;
            }
            if ( ! aSrp(24251, s, d, testValue) ) {
                return false;
            }
            return true;
        }
        //  Try 5 "random" primes
        if ( ! aSrp(37, s, d, testValue) ) {
            return false;
        }
        if ( ! aSrp(47, s, d, testValue) ) {
            return false;
        }
        if ( ! aSrp(61, s, d, testValue) ) {
            return false;
        }
        if ( ! aSrp(73, s, d, testValue) ) {
            return false;
        }
        if ( ! aSrp(83, s, d, testValue) ) {
            return false;
        }
        //throw new RuntimeException("ERROR isPrime:  Value too large = "+testValue);
        return true;
    }

    private static final boolean aSrp(int a, int s, long d, long n) {
        long modPow = modPow(a, d, n);
        //System.out.println("a = "+a+", s = "+s+", d = "+d+", n = "+n+", modpow = "+modPow);
        if ( modPow == 1 ) {
            return true;
        }
        int twoExpR = 1;
        for ( int r = 0 ; r < s ; r++ ) {
            if ( modPow(modPow, twoExpR, n) == n-1 ) {
                return true;
            }
            twoExpR *= 2;
        }
        return false;
    }
    
    private static final long SQRT = (long) Math.sqrt(Long.MAX_VALUE);
    
    public static final long modPow(long base, long exponent, long modulus) {
        long result = 1;
        while ( exponent > 0 ) {
            if ( exponent % 2 == 1 ) {
                if ( result > SQRT || base > SQRT ) {
                    result = multiply(result, base, modulus);
                }
                else {
                    result = (result * base) % modulus;
                }
            }
            exponent >>= 1;
            if ( base > SQRT ) {
                base = multiply(base, base, modulus);
            }
            else {
                base = (base * base) % modulus;
            }
        }
        return result;
    }


    //  Result is a*b % mod, without overflow.
    public static final long multiply(long a, long b, long modulus) {
        long x = 0;
        long y = a % modulus;
        long t;
        while ( b > 0 ) {
            if ( b % 2 == 1 ) {
                t = x + y;
                x = (t > modulus ? t-modulus : t);
            }
            t = y << 1;
            y = (t > modulus ? t-modulus : t);
            b >>= 1;
        }
        return x % modulus;
    }

}
Output:
U(3, 1) = 7 * 13 * 19 = 1729 
U(4, 1) = 7 * 13 * 19 * 37 = 63973 
U(5, 380) = 2281 * 4561 * 6841 * 13681 * 27361 = 26641259752490421121 
U(6, 380) = 2281 * 4561 * 6841 * 13681 * 27361 * 54721 = 1457836374916028334162241 
U(7, 780320) = 4681921 * 9363841 * 14045761 * 28091521 * 56183041 * 112366081 * 224732161 = 24541683183872873851606952966798288052977151461406721 
U(8, 950560) = 5703361 * 11406721 * 17110081 * 34220161 * 68440321 * 136880641 * 273761281 * 547522561 = 53487697914261966820654105730041031613370337776541835775672321 
U(9, 950560) = 5703361 * 11406721 * 17110081 * 34220161 * 68440321 * 136880641 * 273761281 * 547522561 * 1095045121 = 58571442634534443082821160508299574798027946748324125518533225605795841 


Works with: NodeJS 16.14.2
Translation of: Java
const bigInt = require('big-integer');
class ChernicksCarmichaelNumbers {
    static main() {
        for (let n = 3; n < 10; n++) {
            let m = bigInt(0);
            let foundComposite = true;
            let factors = [];
            while (foundComposite) {
                const increment = (n <= 4) 
                    ? bigInt(1) 
                    : bigInt(2).pow(n - 4).times(5);
                m = m.add(increment);
                factors = this.U(n, m);
                foundComposite = false;
                for (let i = 0; i < factors.length; i++) {
                    if (!this.isPrime(factors[i])) {
                        foundComposite = true;
                        break;
                    }
                }
            }
            console.log(`U(${n}, ${m}) = ${this.display(factors)} = ${this.multiply(factors)}`);
        }
    }
    static display(factors) {
        return factors.map(f => f.toString()).join(" * ");
    }
    static multiply(factors) {
        return factors.reduce((acc, val) => acc.times(val), bigInt(1));
    }
    static U(n, m) {
        const factors = [];
        factors.push(bigInt(6).times(m).add(1));
        factors.push(bigInt(12).times(m).add(1));
        for (let i = 1; i <= n - 2; i++) {
            factors.push(bigInt(2).pow(i).times(9).times(m).add(1));
        }
        return factors;
    }
    static MAX = 100000;
    static primes = new Array(ChernicksCarmichaelNumbers.MAX);
    static SIEVE_COMPLETE = false;
    static isPrimeTrivial(test) {
        const num = test.toJSNumber();
        if (!ChernicksCarmichaelNumbers.SIEVE_COMPLETE) {
            ChernicksCarmichaelNumbers.sieve();
            ChernicksCarmichaelNumbers.SIEVE_COMPLETE = true;
        }
        return ChernicksCarmichaelNumbers.primes[num];
    }
    static sieve() {
        for (let i = 2; i < ChernicksCarmichaelNumbers.MAX; i++) {
            ChernicksCarmichaelNumbers.primes[i] = true;
        }
        for (let i = 2; i * i < ChernicksCarmichaelNumbers.MAX; i++) {
            if (ChernicksCarmichaelNumbers.primes[i]) {
                for (let j = i * i; j < ChernicksCarmichaelNumbers.MAX; j += i) {
                    ChernicksCarmichaelNumbers.primes[j] = false;
                }
            }
        }
    }
    static isPrime(testValue) {
        if (testValue.equals(2)) return true;
        if (testValue.isEven()) return false;
        if (testValue.lesser(ChernicksCarmichaelNumbers.MAX)) return ChernicksCarmichaelNumbers.isPrimeTrivial(testValue);
        let d = testValue.minus(1);
        let s = 0;
        while (d.isEven()) {
            s += 1;
            d = d.divide(2);
        }
        const valNum = testValue.toJSNumber();
        if (testValue.lesser(1373653)) {
            if (!ChernicksCarmichaelNumbers.aSrp(2, s, d, testValue)) return false;
            if (!ChernicksCarmichaelNumbers.aSrp(3, s, d, testValue)) return false;
            return true;
        }
        if (testValue.lesser(4759123141)) {
            if (!ChernicksCarmichaelNumbers.aSrp(2, s, d, testValue)) return false;
            if (!ChernicksCarmichaelNumbers.aSrp(7, s, d, testValue)) return false;
            if (!ChernicksCarmichaelNumbers.aSrp(61, s, d, testValue)) return false;
            return true;
        }
        if (testValue.lesser("10000000000000000")) {
            if (!ChernicksCarmichaelNumbers.aSrp(3, s, d, testValue)) return false;
            if (!ChernicksCarmichaelNumbers.aSrp(24251, s, d, testValue)) return false;
            return true;
        }
        // Try 5 "random" primes
        if (!ChernicksCarmichaelNumbers.aSrp(37, s, d, testValue)) return false;
        if (!ChernicksCarmichaelNumbers.aSrp(47, s, d, testValue)) return false;
        if (!ChernicksCarmichaelNumbers.aSrp(61, s, d, testValue)) return false;
        if (!ChernicksCarmichaelNumbers.aSrp(73, s, d, testValue)) return false;
        if (!ChernicksCarmichaelNumbers.aSrp(83, s, d, testValue)) return false;
        return true;
    }
    static aSrp(a, s, d, n) {
        let modPow = ChernicksCarmichaelNumbers.modPow(bigInt(a), d, n);
        if (modPow.equals(1)) {
            return true;
        }
        let twoExpR = bigInt(1);
        for (let r = 0; r < s; r++) {
            if (ChernicksCarmichaelNumbers.modPow(modPow, twoExpR, n).equals(n.minus(1))) {
                return true;
            }
            twoExpR = twoExpR.times(2);
        }
        return false;
    }
    static SQRT = bigInt(3037000499); // Approximate sqrt of MAX_SAFE_INTEGER
    static modPow(base, exponent, modulus) {
        let result = bigInt(1);
        let b = bigInt(base);
        let e = bigInt(exponent);
        while (e.greater(0)) {
            if (e.isOdd()) {
                if (result.greater(ChernicksCarmichaelNumbers.SQRT) || b.greater(ChernicksCarmichaelNumbers.SQRT)) {
                    result = ChernicksCarmichaelNumbers.multiplyInternal(result, b, modulus);
                } else {
                    result = result.times(b).mod(modulus);
                }
            }
            e = e.shiftRight(1);
            if (b.greater(ChernicksCarmichaelNumbers.SQRT)) {
                b = ChernicksCarmichaelNumbers.multiplyInternal(b, b, modulus);
            } else {
                b = b.times(b).mod(modulus);
            }
        }
        return result;
    }
    static multiplyInternal(a, b, modulus) {
        let x = bigInt(0);
        let y = a.mod(modulus);
        let bInt = bigInt(b);
        while (bInt.greater(0)) {
            if (bInt.isOdd()) {
                x = x.add(y);
                if (x.greaterOrEquals(modulus)) {
                    x = x.minus(modulus);
                }
            }
            y = y.shiftLeft(1);
            if (y.greaterOrEquals(modulus)) {
                y = y.minus(modulus);
            }
            bInt = bInt.shiftRight(1);
        }
        return x.mod(modulus);
    }
}
ChernicksCarmichaelNumbers.main();
Output:
U(3, 1) = 7 * 13 * 19 = 1729
U(4, 1) = 7 * 13 * 19 * 37 = 63973
U(5, 380) = 2281 * 4561 * 6841 * 13681 * 27361 = 26641259752490421121
U(6, 380) = 2281 * 4561 * 6841 * 13681 * 27361 * 54721 = 1457836374916028334162241
U(7, 780320) = 4681921 * 9363841 * 14045761 * 28091521 * 56183041 * 112366081 * 224732161 = 24541683183872873851606952966798288052977151461406721
U(8, 950560) = 5703361 * 11406721 * 17110081 * 34220161 * 68440321 * 136880641 * 273761281 * 547522561 = 53487697914261966820654105730041031613370337776541835775672321
U(9, 950560) = 5703361 * 11406721 * 17110081 * 34220161 * 68440321 * 136880641 * 273761281 * 547522561 * 1095045121 = 58571442634534443082821160508299574798027946748324125518533225605795841



using Primes

function trial_pretest(k::UInt64)

    if ((k %  3)==0 || (k %  5)==0 || (k %  7)==0 || (k % 11)==0 ||
        (k % 13)==0 || (k % 17)==0 || (k % 19)==0 || (k % 23)==0)
        return (k <= 23)
    end

    return true
end

function gcd_pretest(k::UInt64)

    if (k <= 107)
        return true
    end

    gcd(29*31*37*41*43*47*53*59*61*67, k) == 1 &&
    gcd(71*73*79*83*89*97*101*103*107, k) == 1
end

function is_chernick(n::Int64, m::UInt64)

    t = 9*m

    if (!trial_pretest(6*m + 1))
        return false
    end

    if (!trial_pretest(12*m + 1))
        return false
    end

    for i in 1:n-2
        if (!trial_pretest((t << i) + 1))
            return false
        end
    end

    if (!gcd_pretest(6*m + 1))
        return false
    end

    if (!gcd_pretest(12*m + 1))
        return false
    end

    for i in 1:n-2
        if (!gcd_pretest((t << i) + 1))
            return false
        end
    end

    if (!isprime(6*m + 1))
        return false
    end

    if (!isprime(12*m + 1))
        return false
    end

    for i in 1:n-2
        if (!isprime((t << i) + 1))
            return false
        end
    end

    return true
end

function chernick_carmichael(n::Int64, m::UInt64)
    prod = big(1)

    prod *= 6*m + 1
    prod *= 12*m + 1

    for i in 1:n-2
        prod *= ((big(9)*m)<<i) + 1
    end

    prod
end

function cc_numbers(from, to)

    for n in from:to

        multiplier = 1

        if (n > 4) multiplier = 1 << (n-4) end
        if (n > 5) multiplier *= 5 end

        m = UInt64(multiplier)

        while true

            if (is_chernick(n, m))
                println("a(", n, ") = ", chernick_carmichael(n, m))
                break
            end

            m += multiplier
        end
    end
end

cc_numbers(3, 10)
Output:
a(3) = 1729
a(4) = 63973
a(5) = 26641259752490421121
a(6) = 1457836374916028334162241
a(7) = 24541683183872873851606952966798288052977151461406721
a(8) = 53487697914261966820654105730041031613370337776541835775672321
a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841
a(10) = 24616075028246330441656912428380582403261346369700917629170235674289719437963233744091978433592331048416482649086961226304033068172880278517841921

(takes ~6.5 minutes)

ClearAll[PrimeFactorCounts, U]
PrimeFactorCounts[n_Integer] := Total[FactorInteger[n][[All, 2]]]
U[n_, m_] := (6 m + 1) (12 m + 1) Product[2^i 9 m + 1, {i, 1, n - 2}]
FindFirstChernickCarmichaelNumber[n_Integer?Positive] := 
 Module[{step, i, m, formula, value},
  step = Ceiling[2^(n - 4)];
  If[n > 5, step *= 5];
  i = step;
  formula = U[n, m];
  PrintTemporary[Dynamic[i]];
  While[True,
   value = formula /. m -> i;
   If[PrimeFactorCounts[value] == n,
    Break[];
    ];
   i += step
   ];
  {i, value}
  ]
FindFirstChernickCarmichaelNumber[3]
FindFirstChernickCarmichaelNumber[4]
FindFirstChernickCarmichaelNumber[5]
FindFirstChernickCarmichaelNumber[6]
FindFirstChernickCarmichaelNumber[7]
FindFirstChernickCarmichaelNumber[8]
FindFirstChernickCarmichaelNumber[9]
Output:
{1,1729}
{1,63973}
{380,26641259752490421121}
{380,1457836374916028334162241}
{780320,24541683183872873851606952966798288052977151461406721}
{950560,53487697914261966820654105730041031613370337776541835775672321}
{950560,58571442634534443082821160508299574798027946748324125518533225605795841}
Library: bignum

Until a(9) a simple primality test using divisions by odd numbers is sufficient. But for a(10), it is necessary to improve the test. We have used here some optimizations found in other solutions:

– eliminating multiples of 3, 5, 7, 11, 13, 17, 19, 23;
– using a probability test which implies to use big integers; so, we have to convert the tested number to a big integer;
– for n >= 5, checking only values of m which are multiple of 5 (in fact, we check only the multiples of 5 × 2^(n-4).

With these optimizations, the program executes in 4-5 minutes.

import strutils, sequtils
import bignum

const
  Max = 10
  Factors: array[3..Max, int] = [1, 1, 2, 4, 8, 16, 32, 64]   # 1 for n=3 then 2^(n-4).
  FirstPrimes = [3, 5, 7, 11, 13, 17, 19, 23]

#---------------------------------------------------------------------------------------------------

iterator factors(n, m: Natural): Natural =
  ## Yield the factors of U(n, m).

  yield 6 * m + 1
  yield 12 * m + 1
  var k = 2
  for _ in 1..(n - 2):
    yield 9 * k * m + 1
    inc k, k

#---------------------------------------------------------------------------------------------------

proc mayBePrime(n: int): bool =
  ## First primality test.

  if n < 23: return true

  for p in FirstPrimes:
    if n mod p == 0:
      return false

  result = true

#---------------------------------------------------------------------------------------------------

proc isChernick(n, m: Natural): bool =
  ## Check if U(N, m) if a Chernick-Carmichael number.

  # Use the first and quick test.
  for factor in factors(n, m):
    if not factor.mayBePrime():
      return false

  # Use the slow probability test (need to use a big int).
  for factor in factors(n, m):
    if probablyPrime(newInt(factor), 25) == 0:
      return false

  result = true

#---------------------------------------------------------------------------------------------------

proc a(n: Natural): tuple[m: Natural, factors: seq[Natural]] =
  ## For a given "n", find the smallest Charnick-Carmichael number.

  var m: Natural = 0
  var incr = (if n >= 5: 5 else: 1) * Factors[n]  # For n >= 5, a(n) is a multiple of 5.

  while true:
    inc m, incr
    if isChernick(n, m):
      return (m, toSeq(factors(n, m)))

#———————————————————————————————————————————————————————————————————————————————————————————————————

import strformat

for n in 3..Max:
  let (m, factors) = a(n)

  stdout.write fmt"a({n}) = U({n}, {m}) = "
  var s = ""
  for factor in factors:
    s.addSep(" × ")
    s.add($factor)
  stdout.write s, '\n'
Output:
a(3) = U(3, 1) = 7 × 13 × 19
a(4) = U(4, 1) = 7 × 13 × 19 × 37
a(5) = U(5, 380) = 2281 × 4561 × 6841 × 13681 × 27361
a(6) = U(6, 380) = 2281 × 4561 × 6841 × 13681 × 27361 × 54721
a(7) = U(7, 780320) = 4681921 × 9363841 × 14045761 × 28091521 × 56183041 × 112366081 × 224732161
a(8) = U(8, 950560) = 5703361 × 11406721 × 17110081 × 34220161 × 68440321 × 136880641 × 273761281 × 547522561
a(9) = U(9, 950560) = 5703361 × 11406721 × 17110081 × 34220161 × 68440321 × 136880641 × 273761281 × 547522561 × 1095045121
a(10) = U(10, 3208386195840) = 19250317175041 × 38500634350081 × 57750951525121 × 115501903050241 × 231003806100481 × 462007612200961 × 924015224401921 × 1848030448803841 × 3696060897607681 × 7392121795215361
cherCar(n)={
  my(C=vector(n));C[1]=6; C[2]=12; for(g=3,n,C[g]=2^(g-2)*9);
  my(i=1); my(N(g)=while(i<=n&ispseudoprime(g*C[i]+1),i=i+1); return(i>n));
     i=1;  my(G(g)=while(i<=n&isprime(g*C[i]+1),i=i+1); return(i>n));
  i=1; if(n>4,i=2^(n-4)); if(n>5,i=i*5); my(m=i); while(!(N(m)&G(m)),m=m+i);
  printf("cherCar(%d): m = %d\n",n,m)}
for(x=3,9,cherCar(x))
Output:
cherCar(3): m = 1
cherCar(4): m = 1
cherCar(5): m = 380
cherCar(6): m = 380
cherCar(7): m = 780320
cherCar(8): m = 950560
cherCar(9): m = 950560
cherCar(10): m = 3208386195840
Library: ntheory
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) });
}
Output:
a(3) = 1729
a(4) = 63973
a(5) = 26641259752490421121
a(6) = 1457836374916028334162241
a(7) = 24541683183872873851606952966798288052977151461406721
a(8) = 53487697914261966820654105730041031613370337776541835775672321
a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841
Library: Phix/mpfr

With some optional cheating

with javascript_semantics
include mpfr.e
mpz {z,p} = mpz_inits(2)
 
function is_chernick(integer n, atom m)
    sequence cf = {}
    integer c = 0
    atom f
    for i=1 to n do
        c += iff(i<=3?6:c)
        f = c*m+1
        if f>23 then
            for p in {3,5,7,11,13,17,19,23} do
                if rmdr(f,p)=0 then return false end if
            end for
        end if
        cf &= f
    end for
    for f in cf do
        if f>107 then
            for p in {29,31,37,41,43,47,53,59,61,67,
                      71,73,79,83,89,97,101,103,107} do
                if rmdr(f,p)=0 then return false end if
            end for
        end if
    end for
    mpz_set_si(p,1)
    for f in cf do
--      mpz_set_d(z,f) -- aside: fails for 17869585606041601 (..600, no real idea why)
        mpz_set_str(z,sprintf("%d",f))
        if not mpz_prime(z) then return false end if
        mpz_mul(p,p,z)
    end for
    progress("")
    printf(1,"U(%d,%d): %s = %s\n",{n,m,mpz_get_short_str(p),join(cf," * ",fmt:="%d")})
    return true
end function

constant expected_results = {0,0,1,1,380,380,780320,950560,950560,3208386195840,31023586121600} 
--                           ^ ^ (unused)
procedure main()
    atom t0 = time()
 
    -- derived from prime factors of the final k, should you find any way to bump 
    -- the multiplier by any of these, that would be good & need culling from this
--  sequence cheat = {0,0,1,1,190,19,4*4877,26*457,13*457,
--                      2*3*7*19*12564169,5*457*21214159}   -- 0s           -- max cheat!
    sequence cheat = {0,0,1,1,1,1,1,1,1,12564169,21214159}  -- 0.0s         -- still cheating!
--  sequence cheat = {0,0,1,1,1,1,1,1,1,2*3*7*19,21214159}  -- 8.3s
--  sequence cheat = {0,0,1,1,1,1,1,1,1,12564169,5*457}     -- 7.8s
--  sequence cheat = {0,0,1,1,1,1,1,1,1,2*3*7*19,5*457}     -- 15.9s
--  sequence cheat = {0,0,1,1,1,1,1,1,1,12564169,457}       -- 38.5s
--  sequence cheat = {0,0,1,1,1,1,1,1,1,1,21214159}         -- 1 hour (est)
--  sequence cheat = {0,0,1,1,1,1,1,1,1,12564169,1}         -- 5 hours (est)

    for n=3 to iff(machine_bits()=32?10:11) do
        atom multiplier = iff(n>4 ? power(2,n-4) : 1), k = 0, t2 = time(), t1 = t2+1
        if n>5 then multiplier *= 5 end if
        while true do
            k += cheat[n]                                   -- (see timings as above)
--          k += 1                                          -- 6 hours (est, without cheating)
            atom m = k * multiplier;
            if is_chernick(n, m) then exit end if
            if time()>t1 then
                atom er = expected_results[n], f = m/er, e = time()-t2
                -- estimated time and time to completion for the current n, fairly
                -- obviously these do not indicate how long any later n might take.
                string est = elapsed_short(e/f), etc = elapsed_short(e*((1-f)/f))
                progress("%d/%d (%.2f%%, est: %s, etc:%s)",{m,er,f*100,est,etc})
                t1 = time()+1
            end if
        end while
    end for
    ?elapsed(time()-t0)
end procedure
main()
Output:

(with some manually added linebreaks)

U(3,1): 1729 = 7 * 13 * 19
U(4,1): 63973 = 7 * 13 * 19 * 37
U(5,380): 26641259752490421121 = 2281 * 4561 * 6841 * 13681 * 27361
U(6,380): 1457836374916028334162241 = 2281 * 4561 * 6841 * 13681 * 27361 * 54721
U(7,780320): 24541683183872873851606952966798288052977151461406721 = 4681921 * 9363841 * 14045761 * 28091521 
                                                                          * 56183041 * 112366081 * 224732161
U(8,950560): 53487697914261966820...37776541835775672321 (62 digits) = 5703361 * 11406721 * 17110081 * 34220161 
                                                                 * 68440321 * 136880641 * 273761281 * 547522561
U(9,950560): 58571442634534443082...25518533225605795841 (71 digits) = 5703361 * 11406721 * 17110081 * 34220161 
                                                    * 68440321 * 136880641 * 273761281 * 547522561 * 1095045121
U(10,3208386195840): 24616075028246330441...68172880278517841921 (146 digits) = 19250317175041 * 38500634350081
                                         * 57750951525121 * 115501903050241 * 231003806100481 * 462007612200961
                                     * 924015224401921 * 1848030448803841 * 3696060897607681 * 7392121795215361
U(11,31023586121600): 25146460461623166913...45789586498697625601 (173 digits) = 186141516729601 * 372283033459201
                     * 558424550188801 * 1116849100377601 * 2233698200755201 * 4467396401510401 * 8934792803020801
                                  * 17869585606041601 * 35739171212083201 * 71478342424166401 * 142956684848332801
"0.0s"

As noted in the comments, I expect that would take about 6 hours without any cheating.

Translation of: Wren
Library: Pluto-bignum
Library: Pluto-table2
Library: Pluto-fmt

Reaches a(9) in 0.06 seconds but a(10) took just under 54 minutes despite the use of GMP for the probable prime tests.

require "bignum"
require "table2"
local fmt = require "fmt"

local min = 3
local max = 10
local zero = bigint.zero
local fact = zero
local factors = table.rep(max, 0)
local big_factors = table.rep(max, zero)
mpz.init()

local function is_prime_pretest(k)
    if k % 3 == 0 or k % 5 == 0 or k % 7 == 0 or  k % 11 == 0 or
       k % 13 == 0 or k % 17 == 0 or k % 19 == 0 or k % 23 == 0 then
        return k <= 23
    end
    return true
end

local function ccfactors(n, m)
    if !is_prime_pretest( 6 * m + 1) then return false end
    if !is_prime_pretest(12 * m + 1) then return false end
    factors[1] =  6 * m + 1
    factors[2] = 12 * m + 1
    local t = 9 * m
    local i = 1
    while i <= n - 2 do
        local tt = (t << i) + 1
        if !is_prime_pretest(tt) then return false end
        factors[i + 2] = tt
        i += 1
    end
    for j = 1, n do
        fact = bigint.new(factors[j])
        if !mpz.isprobableprime(fact, 15) then return false end
        big_factors[j] = fact
    end
    return true
end

local function ccnumbers(start, finish)
    for n = start, finish do
        local mult = 1
        if n > 4 then mult = 1 << (n - 4) end
        if n > 5 then mult *= 5 end
        local m = mult
        while true do
            if ccfactors(n, m) then
                local num = big_factors:slice(1, n):prod()
                fmt.print("a(%d) = %s", n, num)
                fmt.print("m(%d) = %s", n, m)
                fmt.print("Factors: %,s\n", factors:slice(1, n))
                break
            end
            m += mult
        end
    end
end

ccnumbers(min, max)
Output:
a(3) = 1729
m(3) = 1
Factors: {7, 13, 19}

a(4) = 63973
m(4) = 1
Factors: {7, 13, 19, 37}

a(5) = 26641259752490421121
m(5) = 380
Factors: {2281, 4561, 6841, 13681, 27361}

a(6) = 1457836374916028334162241
m(6) = 380
Factors: {2281, 4561, 6841, 13681, 27361, 54721}

a(7) = 24541683183872873851606952966798288052977151461406721
m(7) = 780320
Factors: {4681921, 9363841, 14045761, 28091521, 56183041, 112366081, 224732161}

a(8) = 53487697914261966820654105730041031613370337776541835775672321
m(8) = 950560
Factors: {5703361, 11406721, 17110081, 34220161, 68440321, 136880641, 273761281, 547522561}

a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841
m(9) = 950560
Factors: {5703361, 11406721, 17110081, 34220161, 68440321, 136880641, 273761281, 547522561, 1095045121}

a(10) = 24616075028246330441656912428380582403261346369700917629170235674289719437963233744091978433592331048416482649086961226304033068172880278517841921
m(10) = 3208386195840
Factors: {19250317175041, 38500634350081, 57750951525121, 115501903050241, 231003806100481, 462007612200961, 924015224401921, 1848030448803841, 3696060897607681, 7392121795215361}

SWI Prolog is too slow to solve for a(10), even with optimizing by increasing the multiplier and implementing a trial division check. (actually, my implementation of Miller-Rabin in Prolog already starts with a trial division by small primes.)

?- use_module(library(primality)).

u(3, M, A * B * C) :-
    A is 6*M + 1, B is 12*M + 1, C is 18*M + 1, !.
u(N, M, U0 * D) :-
    succ(Pn, N), u(Pn, M, U0),
    D is 9*(1 << (N - 2))*M + 1.

prime_factorization(A*B) :- prime(B), prime_factorization(A), !.
prime_factorization(A) :- prime(A).

step(N, 1) :- N < 5, !.
step(5, 2) :- !.
step(N, K) :- K is 5*(1 << (N - 4)).

a(N, Factors) :- % due to backtracking nature of Prolog, a(n) will return all chernick-carmichael numbers.
    N > 2, !,
    step(N, I),
    between(1, infinite, J), M is I * J,
    u(N, M, Factors),
    prime_factorization(Factors).

main :-
    forall(
        (between(3, 9, K), once(a(K, Factorization)), N is Factorization),
        format("~w: ~w = ~w~n", [K, Factorization, N])),
    halt.

?- main.

isprime predicate:

prime(N) :-
    integer(N),
    N > 1,
    divcheck(
        N,
        [  2,   3,   5,   7,  11,  13,  17,  19,  23,  29,  31, 
          37,  41,  43,  47,  53,  59,  61,  67,  71,  73,  79,
          83,  89,  97, 101, 103, 107, 109, 113, 127, 131, 137,
         139, 149],
        Result),
    ((Result = prime, !); miller_rabin_primality_test(N)).

divcheck(_, [],    unknown) :- !.
divcheck(N, [P|_], prime) :- P*P > N, !.
divcheck(N, [P|Ps], State) :- N mod P =\= 0, divcheck(N, Ps, State).

miller_rabin_primality_test(N) :-
    bases(Bases, N),
    forall(member(A, Bases), strong_fermat_pseudoprime(N, A)).

miller_rabin_precision(16).

bases([31, 73], N) :- N < 9_080_191, !.
bases([2, 7, 61], N) :- N < 4_759_123_141, !.
bases([2, 325, 9_375, 28_178, 450_775, 9_780_504, 1_795_265_022], N) :-
    N < 18_446_744_073_709_551_616, !. % 2^64
bases(Bases, N) :-
    miller_rabin_precision(T), RndLimit is N - 2,
    length(Bases, T), maplist(random_between(2, RndLimit), Bases).

strong_fermat_pseudoprime(N, A) :-  % miller-rabin strong pseudoprime test with base A.
    succ(Pn, N), factor_2s(Pn, S, D),
    X is powm(A, D, N),
    ((X =:= 1, !); \+ composite_witness(N, S, X)).

composite_witness(_, 0, _) :- !.
composite_witness(N, K, X) :-
    X =\= N-1,
    succ(Pk, K), X2 is (X*X) mod N, composite_witness(N, Pk, X2).

factor_2s(N, S, D) :- factor_2s(0, N, S, D).
factor_2s(S, D, S, D) :- D /\ 1 =\= 0, !.
factor_2s(S0, D0, S, D) :-
    succ(S0, S1), D1 is D0 >> 1,
    factor_2s(S1, D1, S, D).
Output:
3: 7*13*19 = 1729
4: 7*13*19*37 = 63973
5: 2281*4561*6841*13681*27361 = 26641259752490421121
6: 2281*4561*6841*13681*27361*54721 = 1457836374916028334162241
7: 4681921*9363841*14045761*28091521*56183041*112366081*224732161 = 24541683183872873851606952966798288052977151461406721
8: 5703361*11406721*17110081*34220161*68440321*136880641*273761281*547522561 = 53487697914261966820654105730041031613370337776541835775672321
9: 5703361*11406721*17110081*34220161*68440321*136880641*273761281*547522561*1095045121 = 58571442634534443082821160508299574798027946748324125518533225605795841
"""

Python implementation of
http://rosettacode.org/wiki/Chernick%27s_Carmichael_numbers

"""

# use sympy for prime test

from sympy import isprime

# based on C version

def primality_pretest(k):
    if not (k % 3) or not (k % 5) or not (k % 7) or not (k % 11) or not(k % 13) or not (k % 17) or not (k % 19) or not (k % 23):
        return (k <= 23)
        
    return True

def is_chernick(n, m):

    t = 9 * m
    
    if not primality_pretest(6 * m + 1):
        return False
        
    if not primality_pretest(12 * m + 1):
        return False
        
    for i in range(1,n-1):
        if not primality_pretest((t << i) + 1):
            return False
        
    if not isprime(6 * m + 1):
        return False
        
    if not isprime(12 * m + 1):
        return False
        
    for i in range(1,n - 1):
        if not isprime((t << i) + 1):
            return False
        
    return True
    
for n in range(3,10):

    if n > 4:
        multiplier = 1 << (n - 4)
    else:
        multiplier = 1
    
    if n > 5:
        multiplier *= 5
        
        
    k = 1
    
    while True:
        m = k * multiplier
        
        if is_chernick(n, m): 
            print("a("+str(n)+") has m = "+str(m))
            break
            
        k += 1
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

(formerly Perl 6)

Use the ntheory library from Perl for primality testing since it is much, much faster than Raku's built-in .is-prime method.

Translation of: Perl
Library: ntheory
use Inline::Perl5;
use ntheory:from<Perl5> <:all>;

sub chernick-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 +< (($n-4) max 0);
    my $iterator   = $n < 5 ?? (1 .. *) !! (1 .. *).map: * × 5;

    $multiplier × $iterator.first: -> $m {
        [&&] chernick-factors($n, $m × $multiplier).map: { is_prime($_) }
    }

}

for 3 .. 9 -> $n {
    my $m = chernick-carmichael-number($n);
    my @f = chernick-factors($n, $m);
    say "U($n, $m): {[×] @f} = {@f.join(' ⨉ ')}";
}
Output:
U(3, 1): 1729 = 7 ⨉ 13 ⨉ 19
U(4, 1): 63973 = 7 ⨉ 13 ⨉ 19 ⨉ 37
U(5, 380): 26641259752490421121 = 2281 ⨉ 4561 ⨉ 6841 ⨉ 13681 ⨉ 27361
U(6, 380): 1457836374916028334162241 = 2281 ⨉ 4561 ⨉ 6841 ⨉ 13681 ⨉ 27361 ⨉ 54721
U(7, 780320): 24541683183872873851606952966798288052977151461406721 = 4681921 ⨉ 9363841 ⨉ 14045761 ⨉ 28091521 ⨉ 56183041 ⨉ 112366081 ⨉ 224732161
U(8, 950560): 53487697914261966820654105730041031613370337776541835775672321 = 5703361 ⨉ 11406721 ⨉ 17110081 ⨉ 34220161 ⨉ 68440321 ⨉ 136880641 ⨉ 273761281 ⨉ 547522561
U(9, 950560): 58571442634534443082821160508299574798027946748324125518533225605795841 = 5703361 ⨉ 11406721 ⨉ 17110081 ⨉ 34220161 ⨉ 68440321 ⨉ 136880641 ⨉ 273761281 ⨉ 547522561 ⨉ 1095045121

Modules: How to use
Modules: Source code

Below program uses the improvements as given in Discussion and several other entries. The procedure Prime() is in library Numbers (Miller-Rabin with many tricks).

-- 23 Aug 2025
include Setting

say 'CHERNICKS'' CARMICHAEL NUMBERS'
say version
say
numeric digits 80
say Copies('-',80)
say 'n   m(n) a(n)'
say Copies('-',80)
do n = 3 to 9
   mp = 1
   if n > 4 then
      mp = 2**(n-4)
   if n > 5 then
      mp = mp*5
   k = 0
   do x = 1
      k = k+1; m = mp*k; f.1 = 6*m+1
      if \ Prime(f.1) then
         iterate x
      f.2 = 12*m+1
      if \ Prime(f.2) then
         iterate x
      f = 2
      do i = 1 to n-2
         f = f+1; f.f = 2**i*9*m+1
         if \ Prime(f.f) then
            iterate x
      end
      a = 1
      do i = 1 to f
         a = a*f.i
      end
      say n Right(m,6) a
      leave x
   end
end
say Copies('-',80)
say Format(Time('e'),3,3) 'seconds'
say
exit

include Math
Output:
CHERNICKS' CARMICHAEL NUMBERS - 3 Mar 2025
REXX-ooRexx_5.0.0(MT)_64-bit 6.05 23 Dec 2022

--------------------------------------------------------------------------------
n   m(n) a(n)
--------------------------------------------------------------------------------
3      1 1729
4      1 63973
5    380 26641259752490421121
6    380 1457836374916028334162241
7 780320 24541683183872873851606952966798288052977151461406721
8 950560 53487697914261966820654105730041031613370337776541835775672321
9 950560 58571442634534443082821160508299574798027946748324125518533225605795841
--------------------------------------------------------------------------------
  1.406 seconds

a(10) was not reachable with REXX. It would run for weeks.

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(' * ')}" })
}
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
Translation of: Go
Library: Wren-big
Library: Wren-fmt

Based on Go's 'more efficient' version. Reaches a(9) in just over 0.1 seconds but a(10) would still be out of reasonable reach for Wren so I've had to be content with that.

import "./big" for BigInt, BigInts
import "./fmt" for Fmt

var min = 3
var max = 9
var prod = BigInt.zero
var fact = BigInt.zero
var factors = List.filled(max, 0)
var bigFactors = List.filled(max, null)

var init = Fn.new {
    for (i in 0...max) bigFactors[i] = BigInt.zero
}

var isPrimePretest = Fn.new { |k|
    if (k%3 == 0 || k%5 == 0 || k%7 == 0 || k%11 == 0 ||
       (k%13 == 0) || k%17 == 0 || k%19 == 0 || k%23 == 0) return k <= 23
    return true
}

var ccFactors = Fn.new { |n, m|
    if (!isPrimePretest.call(6*m + 1)) return false
    if (!isPrimePretest.call(12*m + 1)) return false
    factors[0] = 6*m + 1
    factors[1] = 12*m + 1
    var t = 9 * m
    var i = 1
    while (i <= n-2) {
        var tt = (t << i) + 1
        if (!isPrimePretest.call(tt)) return false
        factors[i+1] = tt
        i = i + 1
    }
    for (i in 0...n) {
        fact = BigInt.new(factors[i])
        if (!fact.isProbablePrime(1)) return false
        bigFactors[i] = fact
    }
    return true
}

var ccNumbers = Fn.new { |start, end|
    for (n in start..end) {
        var mult = 1
        if (n > 4) mult = 1 << (n - 4)
        if (n > 5) mult = mult * 5
        var m = mult
        while (true) {
            if (ccFactors.call(n, m)) {
                var num = BigInts.prod(bigFactors.take(n))
                Fmt.print("a($d) = $i", n, num)
                Fmt.print("m($d) = $d", n, m)
                Fmt.print("Factors: $n\n", factors[0...n])
                break
            }
            m = m + mult
        }
    }
}

init.call()
ccNumbers.call(min, max)
Output:
a(3) = 1729
m(3) = 1
Factors: [7, 13, 19]

a(4) = 63973
m(4) = 1
Factors: [7, 13, 19, 37]

a(5) = 26641259752490421121
m(5) = 380
Factors: [2281, 4561, 6841, 13681, 27361]

a(6) = 1457836374916028334162241
m(6) = 380
Factors: [2281, 4561, 6841, 13681, 27361, 54721]

a(7) = 24541683183872873851606952966798288052977151461406721
m(7) = 780320
Factors: [4681921, 9363841, 14045761, 28091521, 56183041, 112366081, 224732161]

a(8) = 53487697914261966820654105730041031613370337776541835775672321
m(8) = 950560
Factors: [5703361, 11406721, 17110081, 34220161, 68440321, 136880641, 273761281, 547522561]

a(9) = 58571442634534443082821160508299574798027946748324125518533225605795841
m(9) = 950560
Factors: [5703361, 11406721, 17110081, 34220161, 68440321, 136880641, 273761281, 547522561, 1095045121]
Translation of: Go
Library: GMP

GNU Multiple Precision Arithmetic Library

Using GMP (probabilistic primes), because it is easy and fast to check primeness.

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;
      }
   }
}
ccNumbers(3,9);
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
Cookies help us deliver our services. By using our services, you agree to our use of cookies.