Project Euler Homework
|
00001 #include <iostream> 00002 using namespace std; 00003 00004 const unsigned MAX = 1000000; 00005 class prime_table 00006 { 00007 bool x[MAX]; 00008 public: 00009 prime_table(); 00010 bool has(unsigned k); 00011 unsigned next(unsigned n); 00012 }; 00013 00014 prime_table::prime_table() 00015 { 00016 //assume all except 0,1 are prime 00017 x[0]=x[1]=0; 00018 for (bool* p=x+2;p-x<MAX;p++)*p=1; 00019 00020 for (unsigned n = 2; n < MAX;n = next(n)) { 00021 unsigned idx=n+n; 00022 while (idx < MAX) { 00023 x[idx]=0; 00024 idx+=n; 00025 } 00026 } 00027 } 00028 00029 unsigned prime_table::next(unsigned n) 00030 { 00031 if (n>=MAX)return MAX; 00032 bool* p = x+n; 00033 do { 00034 p++; 00035 if (*p)return (p-x); 00036 } while (p-x < MAX); 00037 return MAX; 00038 } 00039 00040 bool prime_table::has(unsigned k) 00041 { 00042 if (k>=MAX) { 00043 cerr << "Error: overflow"; 00044 return 0; 00045 } 00046 return x[k]; 00047 } 00048 00049 unsigned pow10(unsigned p) 00050 { 00051 unsigned prod=1; 00052 for (unsigned i=1;i<=p;i++) 00053 prod*=10; 00054 return prod; 00055 } 00056 00057 unsigned num_length(unsigned x) 00058 { 00059 unsigned len=0; 00060 for (;x>0;x/=10) 00061 len++; 00062 return len; 00063 } 00064 00065 inline unsigned circulate(unsigned y,unsigned len) 00066 { 00067 return y/10+(y%10)*pow10(len-1); //shift the right-most digit to left 00068 } 00069 00070 class lookup_table 00071 { 00072 bool x[MAX]; 00073 public: 00074 lookup_table() { 00075 for (unsigned i=0;i<MAX;i++) 00076 x[i]=0; 00077 } 00078 void mark(unsigned k) { 00079 x[k]=1; 00080 } 00081 unsigned count() { 00082 unsigned cnt=0; 00083 for (unsigned i=0;i<MAX;i++) 00084 if (x[i]) 00085 cnt++; 00086 return cnt; 00087 } 00088 bool has(unsigned k) { 00089 if (k>=MAX) { 00090 cerr << "Error: overflow"; 00091 return 0; 00092 } 00093 return x[k]; 00094 } 00095 }; 00096 00097 00098 00099 int main() 00100 { 00101 prime_table primes; 00102 lookup_table circular_primes; 00103 00104 unsigned count=0; 00105 for (unsigned p=2;p<MAX;p=primes.next(p)) { 00106 //if p is already a circular prime, skip it 00107 if (circular_primes.has(p))continue; 00108 00109 //check if p is circular 00110 unsigned len=num_length(p); 00111 unsigned y=p; 00112 bool flag=1; 00113 for (unsigned count=1;count<=len;count++) { 00114 y = circulate(y,len); 00115 if (!primes.has(y)) { 00116 flag=0; 00117 break; 00118 } 00119 } 00120 //record all circular primes 00121 if (flag) 00122 for (unsigned count=1;count<=len;count++) { 00123 y = circulate(y,len); 00124 circular_primes.mark(y); 00125 //cout << y << '\t'; 00126 } 00127 } 00128 cout << circular_primes.count() << endl; 00129 return 0; 00130 }