A solution for the "Carmichael Numbers" problem
Problem description:
http://icpcres.ecs.baylor.edu/onlinejudge/external/100/10006.html
Author: Joana Matos Fonseca da Trindade
Date: 2008.04.24
1 2 /* 3 * Solution for "Carmichael Numbers" problem. 4 * UVa ID: 10006 5 */ 6 #include <iostream> 7 #include <math.h> 8 9 #define MAXPRIME 65001 10 11 using namespace std; 12 13 /* 14 * Modular exponentiation algorithm. Returns b^e mod m. 15 */ 16 unsigned long long fast_mod_pow(unsigned long long b, unsigned long long e, unsigned long long m) { 17 unsigned long long r = 1; 18 while (e > 0) { 19 if ((e & 1) == 1) { 20 r = (r * b) % m; 21 } 22 e >>= 1; 23 b = (b * b) % m; 24 } 25 return r; 26 } 27 28 /* 29 * Generates all prime numbers up to MAXPRIME. Based on 30 * the Sieve of Eratosthenes. 31 */ 32 void gen_primes(bool p[]) { 33 p[0] = p[1] = false; 34 35 /* 36 * starting at number 2 and going to the upper limit, mark 37 * all numbers as potential primes 38 */ 39 for (int i=2; i<MAXPRIME; i++) { 40 p[i] = true; 41 } 42 43 int m = floor(sqrt(MAXPRIME)); 44 int n; 45 /* 46 * mark all multiples of a prime as non-primes. this has to be done for primes 47 * only up to the square root, since every number in the array has at least 48 * one factor smaller than the square root of the limit. 49 */ 50 for (int i=2; i<m; i++) { 51 if (p[i]) { 52 n = MAXPRIME / i; 53 for (int j=2; j<=n; j++) { 54 p[i * j] = false; 55 } 56 } 57 } 58 } 59 60 /* generates all carmichael numbers up to the given limit by performing the fermat test */ 61 void gen_carmi(bool c[], bool p[]) { 62 63 /* initialize carmichael numbers array with false */ 64 memset(c, 0, MAXPRIME * sizeof(bool)); 65 66 /* 67 * starting from the first non-prime, mark all 68 * odd numbers as potential carmichael numbers 69 */ 70 for (int i=9; i<MAXPRIME; i+=2) { 71 c[i] = true; 72 } 73 74 /* 75 * again, for all odd numbers, we exclude the primes and perform 76 * the fermat test for 2 <= a <= n-1. 77 */ 78 for (int n=9; n<MAXPRIME; n+=2) { 79 /* VERY IMPORTANT! check first if this number is prime, otherwise we get TLE */ 80 if (p[n]) { 81 c[n] = false; 82 continue; 83 } 84 for (int a=2; a<=n-1; a++) { 85 if (fast_mod_pow(a,n,n) != a) { 86 c[n] = false; 87 break; 88 } 89 } 90 } 91 } 92 93 /* main */ 94 int main() { 95 unsigned long long n; /* number */ 96 unsigned long long a; /* a of the fermat test */ 97 bool prime[MAXPRIME]; /* prime numbers array */ 98 bool carmi[MAXPRIME]; /* carmichael numbers array */ 99 100 gen_primes(prime); 101 gen_carmi(carmi, prime); 102 103 while (cin >> n && (n != 0)) { 104 if (carmi[n]) { 105 cout << "The number " << n << " is a Carmichael number." << endl; 106 } else { 107 cout << n << " is normal." << endl; 108 } 109 } 110 return 0; 111 }