Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
Duplicates are just noise here. Rule 2 only asks whether a value appears at least once, and rule 1 treats equal values identically, so work with the distinct set of array values.
If you choose some into , then itself must appear in the array, because is one of the positive multiples of up to . So every chosen number comes from .
Look at a value that has no proper divisor also in . To cover , the chosen divisor must be in and divide , so the only possible choice is itself. These minimal values are forced.
Once all divisibility-minimal values are chosen, they cover every value in : repeatedly move from any non-minimal value to a smaller divisor in until you hit a minimal one. No set-cover nonsense needed; the answer is pinned down.
For a forced value , rule 2 holds iff the number of distinct array values divisible by equals . Enumerate divisors of each distinct array value to count this efficiently and to detect which values are minimal.
First, delete duplicate values. Only appearance matters, not frequency. Let be the set of distinct values in the array.
The tempting wrong read is: this is minimum set cover. That would be ugly. Thankfully, divisibility makes the answer basically forced.
Call a value minimal if there is no different value such that .
Example: in , the minimal values are and .
Now observe something important: if is chosen into , then must belong to . Why? Rule 2 says every positive multiple of up to appears in the array. One of those multiples is itself. So selected values cannot come from thin air.
Take a minimal value . Rule 1 says some chosen must divide . But we just proved . Since has no proper divisor inside , the only possibility is .
So every minimal value of is forced into every valid answer. This is the key. The problem is not asking us to hunt for a clever subset; the subset already walked into the room wearing a name tag.
Let be the set of minimal values in .
Every valid answer must contain all of , so no valid answer can have size less than .
If every value in satisfies rule 2, then choosing exactly works:
Therefore:
For a value , rule 2 says all multiples
appear in .
There are exactly such multiples. So rule 2 is equivalent to:
number of distinct values in S divisible by b == floor(k / b)
The left side can never exceed the right side, because all values are between and . If the count matches, every possible multiple is present. If it is smaller, at least one multiple is missing. Brutally simple.
We need two things for each distinct value :
Do this by iterating over each distinct value , generating all divisors of , and checking which divisors are also in using a hash map.
For every divisor of with :
divCnt[d], because is divisible by ;After this pass, the minimal values are exactly the unmarked values. For each one, check divCnt[b] == k / b.
Lemma 1. Every selected value must be in .
Rule 2 requires every positive multiple of up to to appear in the array. Since itself is such a multiple, appears in the array, so .
Lemma 2. Every minimal value of must be selected in any complete set.
Let be minimal. Rule 1 requires some selected with . By Lemma 1, . Since has no proper divisor in , the only possible such is . Thus must be selected.
Lemma 3. If all minimal values satisfy rule 2, selecting exactly all minimal values covers every value in .
For any , if is minimal, it is selected. Otherwise, has a smaller divisor in . Repeating this process must eventually stop, because the values strictly decrease. The final value is a minimal divisor of , and it is selected. Hence rule 1 holds for .
Lemma 4. For , rule 2 holds iff divCnt[b] == floor(k / b).
There are exactly positive multiples of not exceeding . divCnt[b] counts how many of those multiples appear in . Since contains only values from to , equality means all multiples appear, and inequality means at least one is missing.
Theorem. The algorithm outputs iff no complete set exists; otherwise it outputs a complete set of minimum possible size.
By Lemma 2, every solution must include all minimal values. If any minimal value fails rule 2, no solution can exist. If all pass, Lemma 3 shows the set of all minimal values is complete, and Lemma 2 shows no smaller complete set is possible. So the algorithm is correct.
Let and let be the number of divisors of .
The main pass does hash lookups. Values are at most , so divisor counts are small enough for this approach. The solution factors numbers using primes up to plus a tiny deterministic primality test, so huge prime inputs do not become a modulo-operation crime scene.
Memory usage is .
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int LIM = 31623;
vector<int> buildPrimes() {
vector<int> primes;
vector<bool> composite(LIM + 1, false);
for (int i = 2; i <= LIM; i++) {
if (composite[i]) continue;
primes.push_back(i);
if (1LL * i * i <= LIM) {
for (ll j = 1LL * i * i; j <= LIM; j += i) {
composite[(int)j] = true;
}
}
}
return primes;
}
vector<int> primes = buildPrimes();
ll modPow(ll a, ll e, ll mod) {
ll r = 1;
while (e) {
if (e & 1) r = r * a % mod;
a = a * a % mod;
e >>= 1;
}
return r;
}
bool isPrimeInt(int n) {
if (n < 2) return false;
for (int p : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}) {
if (n % p == 0) return n == p;
}
int d = n - 1, s = 0;
while ((d & 1) == 0) {
d >>= 1;
s++;
}
for (int a : {2, 3, 5, 7}) {
if (a >= n) continue;
ll x = modPow(a, d, n);
if (x == 1 || x == n - 1) continue;
bool passed = false;
for (int r = 1; r < s; r++) {
x = x * x % n;
if (x == n - 1) {
passed = true;
break;
}
}
if (!passed) return false;
}
return true;
}
vector<pair<int, int>> factorize(int x) {
vector<pair<int, int>> f;
if (x <= 1) return f;
if (isPrimeInt(x)) {
f.push_back({x, 1});
return f;
}
int y = x;
for (int p : primes) {
if (1LL * p * p > y) break;
if (y % p != 0) continue;
int e = 0;
while (y % p == 0) {
y /= p;
e++;
}
f.push_back({p, e});
if (y > 1 && isPrimeInt(y)) {
f.push_back({y, 1});
y = 1;
break;
}
}
if (y > 1) f.push_back({y, 1});
return f;
}
vector<int> divisorsOf(int x) {
auto factors = factorize(x);
int total = 1;
for (auto [p, e] : factors) total *= e + 1;
vector<int> divisors;
divisors.reserve(total);
divisors.push_back(1);
for (auto [p, e] : factors) {
int sz = (int)divisors.size();
int mul = 1;
for (int take = 1; take <= e; take++) {
mul *= p;
for (int i = 0; i < sz; i++) {
divisors.push_back(divisors[i] * mul);
}
}
}
return divisors;
}
struct CustomHash {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15ULL;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + seed);
}
};
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll k;
cin >> n >> k;
vector<int> a(n);
for (int &x : a) cin >> x;
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
int m = (int)a.size();
unordered_map<int, int, CustomHash> id;
id.reserve(2 * m + 1);
id.max_load_factor(0.7);
for (int i = 0; i < m; i++) id[a[i]] = i;
vector<int> divCnt(m, 0);
vector<char> hasProperDivisor(m, false);
for (int i = 0; i < m; i++) {
vector<int> divisors = divisorsOf(a[i]);
for (int d : divisors) {
auto it = id.find(d);
if (it == id.end()) continue;
divCnt[it->second]++;
if (d != a[i]) hasProperDivisor[i] = true;
}
}
vector<int> ans;
bool ok = true;
for (int i = 0; i < m; i++) {
if (hasProperDivisor[i]) continue;
if ((ll)divCnt[i] != k / a[i]) {
ok = false;
break;
}
ans.push_back(a[i]);
}
if (!ok) {
cout << -1 << '\n';
continue;
}
cout << ans.size() << '\n';
for (int x : ans) cout << x << ' ';
cout << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const int LIM = 31623;
vector<int> buildPrimes() {
vector<int> primes;
vector<bool> composite(LIM + 1, false);
for (int i = 2; i <= LIM; i++) {
if (composite[i]) continue;
primes.push_back(i);
if (1LL * i * i <= LIM) {
for (ll j = 1LL * i * i; j <= LIM; j += i) {
composite[(int)j] = true;
}
}
}
return primes;
}
vector<int> primes = buildPrimes();
ll modPow(ll a, ll e, ll mod) {
ll r = 1;
while (e) {
if (e & 1) r = r * a % mod;
a = a * a % mod;
e >>= 1;
}
return r;
}
bool isPrimeInt(int n) {
if (n < 2) return false;
for (int p : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}) {
if (n % p == 0) return n == p;
}
int d = n - 1, s = 0;
while ((d & 1) == 0) {
d >>= 1;
s++;
}
for (int a : {2, 3, 5, 7}) {
if (a >= n) continue;
ll x = modPow(a, d, n);
if (x == 1 || x == n - 1) continue;
bool passed = false;
for (int r = 1; r < s; r++) {
x = x * x % n;
if (x == n - 1) {
passed = true;
break;
}
}
if (!passed) return false;
}
return true;
}
vector<pair<int, int>> factorize(int x) {
vector<pair<int, int>> f;
if (x <= 1) return f;
if (isPrimeInt(x)) {
f.push_back({x, 1});
return f;
}
int y = x;
for (int p : primes) {
if (1LL * p * p > y) break;
if (y % p != 0) continue;
int e = 0;
while (y % p == 0) {
y /= p;
e++;
}
f.push_back({p, e});
if (y > 1 && isPrimeInt(y)) {
f.push_back({y, 1});
y = 1;
break;
}
}
if (y > 1) f.push_back({y, 1});
return f;
}
vector<int> divisorsOf(int x) {
auto factors = factorize(x);
int total = 1;
for (auto [p, e] : factors) total *= e + 1;
vector<int> divisors;
divisors.reserve(total);
divisors.push_back(1);
for (auto [p, e] : factors) {
int sz = (int)divisors.size();
int mul = 1;
for (int take = 1; take <= e; take++) {
mul *= p;
for (int i = 0; i < sz; i++) {
divisors.push_back(divisors[i] * mul);
}
}
}
return divisors;
}
struct CustomHash {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15ULL;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL;
x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL;
return x ^ (x >> 31);
}
size_t operator()(uint64_t x) const {
static const uint64_t seed = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + seed);
}
};
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
ll k;
cin >> n >> k;
vector<int> a(n);
for (int &x : a) cin >> x;
sort(a.begin(), a.end());
a.erase(unique(a.begin(), a.end()), a.end());
int m = (int)a.size();
unordered_map<int, int, CustomHash> id;
id.reserve(2 * m + 1);
id.max_load_factor(0.7);
for (int i = 0; i < m; i++) id[a[i]] = i;
vector<int> divCnt(m, 0);
vector<char> hasProperDivisor(m, false);
for (int i = 0; i < m; i++) {
vector<int> divisors = divisorsOf(a[i]);
for (int d : divisors) {
auto it = id.find(d);
if (it == id.end()) continue;
divCnt[it->second]++;
if (d != a[i]) hasProperDivisor[i] = true;
}
}
vector<int> ans;
bool ok = true;
for (int i = 0; i < m; i++) {
if (hasProperDivisor[i]) continue;
if ((ll)divCnt[i] != k / a[i]) {
ok = false;
break;
}
ans.push_back(a[i]);
}
if (!ok) {
cout << -1 << '\n';
continue;
}
cout << ans.size() << '\n';
for (int x : ans) cout << x << ' ';
cout << '\n';
}
}