-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathP897.cpp
135 lines (123 loc) · 2.68 KB
/
P897.cpp
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
struct PermutationNode {
PermutationNode *next;
int val;
};
struct PermutationHandler {
PermutationNode *nodes;
PermutationHandler(int size) {
nodes = new PermutationNode[size+1];
for(int i = 0; i < size; ++i) {
nodes[i+1].val = i;
nodes[i].next = &(nodes[i+1]);
}
nodes[size].next = NULL;
}
~PermutationHandler() {
delete[] nodes;
}
PermutationNode* root() {
return &(nodes[0]);
}
};
#define PRIME_LEN 5000000
class PrimeHandler {
bitset<PRIME_LEN> primes;
public:
void init() {
primes.set();
// Sieve primes:
for(int i = 0; i*i < PRIME_LEN; ++i) {
if(!primes[i])
continue;
// Mark all uneven multiples as non-prime:
int basePrime = 1+2*(i+1);
for(int multiple = 3; true; multiple += 2) {
int notAPrime = basePrime*multiple;
int notAPrimeI = notAPrime/2-1;
if(notAPrimeI >= PRIME_LEN)
break;
primes.set(notAPrimeI, false);
}
}
}
bool isPrime(int n) const {
if(n == 2)
return true;
if(n < 2 || (n%2==0))
return false;
return primes[n/2-1];
}
bool isAnagrammaticPrime(const int i, int const * const orig, int *perm, const int len, PermutationHandler &ph) {
if(i == len) {
int n = 0;
for(int j = 0; j < len; ++j) {
n = 10*n + perm[j];
}
return isPrime(n);
}
// try all combinations:
PermutationNode *node = ph.root();
while(node->next != NULL) {
PermutationNode *n = node->next;
node->next = n->next;
perm[i] = orig[n->val];
if(!isAnagrammaticPrime(i+1, orig, perm, len, ph)) {
node->next = n;
return false;
}
node->next = n; // n->next is already set (never changes)
node = n;
}
return true;
}
bool isAnagrammaticPrime(int n) {
//cerr << "Checking " << n << endl;
int digits = 0;
int orig[8];
int perm[8];
for(int i = 0; n > 0; ++i) {
++digits;
orig[i] = n%10;
n/=10;
}
PermutationHandler ph(digits);
return isAnagrammaticPrime(0, orig, perm, digits, ph);
}
int nextPrime(int n) const {
if(n < 2)
return 2;
if(n == 2)
return 3;
if((n & 1) == 0)
--n;
int ni = n/2;
while(!primes[ni]) {
++ni;
}
return 1+(ni+1)*2;
}
int nextAnagrammaticPrime(int L) {
int U = 10;
while(U <= L)
U*=10;
L = nextPrime(L);
//cerr << "Running " << L << " -> " << U << endl;
while(L < U) {
if(isAnagrammaticPrime(L))
return L;
L = nextPrime(L);
}
return 0;
}
};
int main() {
PrimeHandler ph;
ph.init();
long L;
while(true) {
cin >> L;
if(L == 0)
return 0;
cout << ph.nextAnagrammaticPrime(L) << endl;
}
}