-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest.cpp
More file actions
100 lines (82 loc) · 2.24 KB
/
Copy pathtest.cpp
File metadata and controls
100 lines (82 loc) · 2.24 KB
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
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <numeric>
using namespace std;
const int MAXN = 10000005;
vector<int> min_prime(MAXN);
vector<int> primes;
vector<int> grundy;
void sieve(int max_n) {
iota(min_prime.begin(), min_prime.begin() + max_n + 1, 0);
for (int i = 2; i <= max_n; i++) {
if (min_prime[i] == i) {
primes.push_back(i);
}
for (int p : primes) {
long long prod = (long long)i * p;
if (prod > max_n) break;
min_prime[prod] = p;
if (i % p == 0) break;
}
}
}
void compute_grundy(int max_n) {
grundy.resize(max_n + 1);
grundy[1] = 0; // Base case: no moves from 1
for (int u = 2; u <= max_n; u++) {
set<int> reachable_grundy;
// Move 1: Divide by prime factors
int tmp = u;
while (tmp > 1) {
int p = min_prime[tmp];
int v = u / p;
reachable_grundy.insert(grundy[v]);
while (tmp % p == 0) {
tmp /= p;
}
}
// Move 2: Multiply by primes
for (int p : primes) {
long long v = (long long)u * p;
if (v > max_n) break;
reachable_grundy.insert(grundy[(int)v]);
}
// Compute MEX (minimal excludant)
int mex = 0;
while (reachable_grundy.count(mex)) {
mex++;
}
grundy[u] = mex;
}
}
int main() {
int t;
cout << "Enter number of test cases: ";
cin >> t;
vector<int> queries(t);
int max_n = 0;
for (int i = 0; i < t; i++) {
cin >> queries[i];
max_n = max(max_n, queries[i]);
}
sieve(max_n);
compute_grundy(max_n);
for (int n : queries) {
int winning_move = -1;
// Find first even number with Grundy number 0
for (int start = 2; start <= n; start += 2) {
if (grundy[start] == 0) {
winning_move = start;
break;
}
}
if (winning_move != -1) {
cout << "first " << winning_move << "\n";
} else {
cout << "second\n";
}
}
return 0;
}