-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathdivisor-game.cpp
147 lines (137 loc) · 3.88 KB
/
divisor-game.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
136
137
138
139
140
141
142
143
144
145
146
147
// Time: O(1)
// Space: O(1)
// math
class Solution {
public:
bool divisorGame(int n) {
// 1. if we get an even, we can choose x = 1
// to make the opponent always get an odd
// 2. if the opponent gets an odd, he can only choose x = 1 or other odds
// and we can still get an even
// 3. at the end, the opponent can only choose x = 1 and we win
// 4. in summary, we win if only if we get an even and
// keeps even until the opponent loses
return n % 2 == 0;
}
};
// Time: O(nlogn)
// Space: O(nlogn)
// dp, number theory
class Solution2 {
public:
bool divisorGame(int n) {
const auto& factors = [](int n) {
vector<vector<int>> result(n + 1);
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; j += i) {
result[j].emplace_back(i);
}
}
return result;
};
const auto& FACTORS = factors(n);
vector<bool> dp(n + 1);
for (int i = 2; i <= n; ++i) {
for (const auto& j : FACTORS[i]) {
if (j != i && !dp[i - j]) {
dp[i] = true;
break;
}
}
}
return dp[n];
}
};
// Time: O(nlogn)
// Space: O(nlogn)
// memoization, number theory
class Solution3 {
public:
bool divisorGame(int n) {
const auto& factors = [](int n) {
vector<vector<int>> result(n + 1);
for (int i = 1; i <= n; ++i) {
for (int j = i; j <= n; j += i) {
result[j].emplace_back(i);
}
}
return result;
};
const auto& FACTORS = factors(n);
vector<int> lookup(n + 1, -1);
const function<int (int)> memoization = [&](int n) {
if (lookup[n] == -1) {
int result = 0;
for (const auto& i : FACTORS[n]) {
if (i != n && !memoization(n - i)) {
result = 1;
break;
}
}
lookup[n] = result;
}
return lookup[n];
};
return memoization(n);
}
};
// Time: O(n^(3/2))
// Space: O(n)
// memoization
class Solution4 {
public:
bool divisorGame(int n) {
vector<int> lookup(n + 1, -1);
const function<int (int)> memoization = [&](int n) {
if (lookup[n] == -1) {
int result = 0;
for (auto i = 1; i * i <= n; ++i) {
if (n % i) {
continue;
}
if (i != n && !memoization(n - i)) {
result = 1;
break;
}
const int j = n / i;
if (j == i) {
continue;
}
if (j != n && !memoization(n - j)) {
result = 1;
break;
}
}
lookup[n] = result;
}
return lookup[n];
};
return memoization(n);
}
};
// Time: O(n^2)
// Space: O(n)
// memoization
class Solution5 {
public:
bool divisorGame(int n) {
vector<int> lookup(n + 1, -1);
const function<int (int)> memoization = [&](int n) {
if (lookup[n] == -1) {
int result = 0;
for (auto i = 1; i <= n; ++i) {
if (n % i) {
continue;
}
if (i != n && !memoization(n - i)) {
result = 1;
break;
}
}
lookup[n] = result;
}
return lookup[n];
};
return memoization(n);
}
};