-
Notifications
You must be signed in to change notification settings - Fork 67
/
Copy pathADADIGIT.cpp
133 lines (118 loc) · 3.47 KB
/
ADADIGIT.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
//
// main.cpp
// practice
//
// Created by Mahmud on 12/16/17.
// Copyright © 2017 Mahmud. All rights reserved.
//
/*
O(N! * sqrt(10^N)) solution HEAVILY based on "CACHING"
Actually, the solution is not different from bruteforcing all possible combinations.
However, the possible numbers which can be derived during factorization process of all numbers,
is not more than N! * log(N!) (expected).
Keep caches (memoize) for all numbers which you come along with during factorization...
*/
#include <iostream>
#include <algorithm>
#include <utility>
#include <cassert>
using namespace std;
const int MAX = 100005;
const int SIZE = 50000000;
int N;
int digits[10];
long long result[2][2];
int primeCount;
int was[MAX], primes[MAX], lp[MAX];
int cache0[SIZE];
long long cache1[SIZE];
int convert(int *digits) {
int s = 0;
for (int i = 0; i < N; i ++) s = 10 * s + digits[i];
return s;
}
void update(int N, pair<int, long long> &result) {
if (N < SIZE) {
cache0[N] = result.first;
cache1[N] = result.second;
}
}
pair<int, long long> calculate(int N) {
if (N < SIZE && cache0[N] != 0) return make_pair(cache0[N], cache1[N]);
int M = N;
if (N < MAX) {
int d = lp[N];
//cerr << N << " ---> " << lp[N] << endl;
int _count = 0;
long long power = d;
while (N % d == 0) {
_count ++;
power *= d;
N /= d;
}
pair<int, long long> get = calculate(N);
//cerr << N << " --> " << get.first << " vs " << get.second << endl;
get.first *= _count + 1;
get.second *= 1LL * (power - 1) / (d - 1);
//cerr << N << " --> " << get.first << " vs " << get.second << endl;
update(M, get);
return get;
}
for (int i = 1; i <= primeCount && primes[i] * primes[i] <= N; i ++) {
if (N % primes[i] == 0) {
int d = primes[i];
int _count = 0;
long long power = d;
while (N % d == 0) {
_count ++;
power *= d;
N /= d;
}
pair<int, long long> get = calculate(N);
get.first *= _count + 1;
get.second *= 1LL * (power - 1) / (d - 1);
update(M, get);
return get;
}
}
if (N > 1) {
pair<int, long long> result = make_pair(2, N + 1);
if (N < SIZE) update(N, result);
return result;
}
assert(false);
return make_pair(-1, -1);
}
int main() {
for (int i = 2; i < MAX; i ++) {
if (was[i]) continue;
primes[++primeCount] = i;
for (int j = i; j < MAX; j += i) {
was[j] = 1;
lp[j] = i;
}
}
cin >> N;
for (int i = 0; i < N; i ++) cin >> digits[i];
int last = 0;
sort(digits, digits + N);
cache0[1] = cache1[1] = 1;
do {
int current = convert(digits);
if (current == last) continue;
last = current;
//cout << "current = " << current << endl;
pair<int, long long> c = calculate(current);
//cout << c.first << " vs " << c.second << endl;
if (c.first > result[0][0]) {
result[0][0] = c.first;
result[0][1] = current;
}
if (c.second > result[1][0]) {
result[1][0] = c.second;
result[1][1] = current;
}
} while (next_permutation(digits, digits + N));
cout << result[0][1] << " " << result[1][1] << endl;
return 0;
}