You are given an array of n integers. You need to split all integers into two groups so that the GCD of all integers in the first group is equal to one and the GCD of all integers in the second group is equal to one.
The GCD of a group of integers is the largest non-negative integer that divides all the integers in the group.
Both groups have to be non-empty.
Input
The first line contains a single integer n (2≤n≤105).
The second line contains n integers a1, a2, …, an (1≤ai≤109) — the elements of the array.
Output
In the first line print “YES” (without quotes), if it is possible to split the integers into two groups as required, and “NO” (without quotes) otherwise.
If it is possible to split the integers, in the second line print n integers, where the i-th integer is equal to 1 if the integer ai should be in the first group, and 2 otherwise.
If there are multiple solutions, print any.
Examples
input
4 2 3 6 7
output
YES 2 2 1 1
input
5 6 15 35 77 22
output
YES 2 1 2 1 1
input
5 6 10 15 1000 75
output
NO
Solution:
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 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 | #include <bits/stdc++.h> using namespace std; namespace factorizer { vector< int > least = {0, 1}; vector< int > primes; int precalculated = 1; void RunLinearSieve( int n) { n = max(n, 1); least.assign(n + 1, 0); primes.clear(); for ( int i = 2; i <= n; i++) { if (least[i] == 0) { least[i] = i; primes.push_back(i); } for ( int x : primes) { if (x > least[i] || i * x > n) { break ; } least[i * x] = x; } } precalculated = n; } void RunSieve( int n) { RunLinearSieve(n); } template < typename T> vector<pair<T, int >> Factorize(T x) { vector<pair<T, int >> ret; for (T i : primes) { T t = x / i; if (i > t) { break ; } if (x == t * i) { int cnt = 0; while (x % i == 0) { x /= i; cnt++; } ret.emplace_back(i, cnt); } } if (x > 1) { ret.emplace_back(x, 1); } return ret; } } // namespace factorizer vector< int > GetFirsts( const vector<pair< int , int >>& a) { vector< int > b; for ( auto & p : a) { b.push_back(p.first); } return b; } mt19937 rng((unsigned int ) chrono::steady_clock::now().time_since_epoch().count()); const int N = 100010; const int MX = 555; int delta[N][2]; int nxt[N][23]; int dist[MX * MX]; int pr[MX * MX]; vector< int > here[N]; int main() { ios::sync_with_stdio( false ); cin.tie(0); int n; cin >> n; vector<pair< int , int >> aa(n); for ( int i = 0; i < n; i++) { cin >> aa[i].first; aa[i].second = i; } shuffle(aa.begin(), aa.end(), rng); vector< int > a(n); vector< int > real_id(n); for ( int i = 0; i < n; i++) { a[i] = aa[i].first; real_id[i] = aa[i].second; } factorizer::RunSieve(40000); for ( int start = 1; start < n; start++) { vector<vector< int >> f = {GetFirsts(factorizer::Factorize(a[0])), GetFirsts(factorizer::Factorize(a[start]))}; vector< int > sz = {( int ) f[0].size(), ( int ) f[1].size()}; for ( int i = start + 1; i < n; i++) { for ( int r = 0; r < 2; r++) { delta[i][r] = 0; for ( int j = 0; j < sz[r]; j++) { if (a[i] % f[r][j] == 0) { delta[i][r] |= (1 << j); } } } } for ( int j = 0; j < sz[0] + sz[1]; j++) { nxt[n][j] = n; } for ( int i = n - 1; i >= start + 1; i--) { for ( int j = 0; j < sz[0]; j++) { if ((delta[i][0] & (1 << j)) == 0) { nxt[i][j] = i; } else { nxt[i][j] = nxt[i + 1][j]; } } for ( int j = 0; j < sz[1]; j++) { if ((delta[i][1] & (1 << j)) == 0) { nxt[i][sz[0] + j] = i; } else { nxt[i][sz[0] + j] = nxt[i + 1][sz[0] + j]; } } } for ( int i = 0; i <= n; i++) { here[i].clear(); } for ( int t = 0; t < (1 << (sz[0] + sz[1])); t++) { dist[t] = n + 1; } int init = (1 << (sz[0] + sz[1])) - 1; dist[init] = start + 1; here[start + 1].push_back(init); for ( int at = start + 1; at < n; at++) { for ( int t : here[at]) { if (dist[t] != at) { continue ; } for ( int bit = 0; bit < sz[0]; bit++) { if ((t & (1 << bit)) == 0) { continue ; } int to = nxt[at][bit]; if (to == n) { continue ; } int nt = t & (delta[to][0] | (((1 << (sz[0] + sz[1])) - 1) ^ ((1 << sz[0]) - 1))); if (to + 1 < dist[nt]) { dist[nt] = to + 1; pr[nt] = t; here[to + 1].push_back(nt); } } for ( int bit = sz[0]; bit < sz[0] + sz[1]; bit++) { if ((t & (1 << bit)) == 0) { continue ; } int to = nxt[at][bit]; if (to == n) { continue ; } int nt = t & ((delta[to][1] << sz[0]) | ((1 << sz[0]) - 1)); if (to + 1 < dist[nt]) { dist[nt] = to + 1; pr[nt] = ~t; here[to + 1].push_back(nt); } } } } if (dist[0] <= n) { cout << "YES" << '\n' ; vector< int > res(n); for ( int i = 0; i < start; i++) { res[real_id[i]] = 1; } res[real_id[start]] = 2; int t = 0; while (t != init) { int id = real_id[dist[t] - 1]; if (pr[t] >= 0) { res[id] = 1; t = pr[t]; } else { res[id] = 2; t = ~pr[t]; } } for ( int i = 0; i < n; i++) { if (res[i] == 0) { res[i] = rng() % 2 + 1; } } for ( int i = 0; i < n; i++) { if (i > 0) { cout << " " ; } cout << res[i]; } cout << '\n' ; return 0; } if (__gcd(a[0], a[start]) == a[0]) { break ; } a[0] = __gcd(a[0], a[start]); } cout << "NO" << '\n' ; return 0; } |