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.
A special number must be divisible by . So if two array elements have different residues modulo , no shared shift can ever work.
For , special means exactly .
When , dividing by preserves the inequality: is special iff is special.
After fixing the operation count modulo , every element either lands on a nonzero multiple of modulo and is immediately fine, or lands on modulo and must be divided by .
Try the seven values with . For each one, recurse only on the residue class where is divisible by , then return .
I used the official Codeforces statement at 2200H - Six Seven and the official Round 1084 tutorial as research references. Public accepted-submission mirrors did not surface quickly, so the proof here is derived from the statement and the official recursive idea.
Let be the exponent of prime in . Then
So is special iff
First, every special number is divisible by , because the left side must be at least . That immediately gives a hard impossibility check: after adding the same number of operations , all values must become multiples of , so all original must have the same residue modulo . If not, answer is . No amount of cleverness fixes modular arithmetic being pissed at you.
Now classify special numbers by modulo .
If , then is special exactly when . Indeed, if but , then , so and . If , then , impossible.
If , write . Then
so
That is the whole trick: numbers divisible by recurse after division by ; nonzero multiples of modulo are already done.
Define as the minimum shared increment needed for all numbers in a multiset . If is empty, . If every element is , then , because is the first special number.
Assume all elements have the same residue modulo . Any valid increment must satisfy
Write
There are only seven possible values of . For each , let
This is the choice where exactly the elements with
land on modulo after adding .
For all other residue classes, is a nonzero multiple of modulo , so it is automatically special. The only elements still requiring work are the ones landing on modulo :
By the recursive property, those are special iff the transformed numbers
become special after more operations. Therefore
If a recursive branch is impossible, treat it as infinity.
Why this is correct:
For the lower bound, take any valid increment . Let and . The chosen corresponds to one residue class modulo landing on zero. Every element in that class must still be special after dividing by , so must be a feasible answer for the transformed set. Hence .
For the upper bound, choose some residue class and let . Add . Elements outside become nonzero multiples of modulo , hence special. Elements inside become times recursively special numbers, hence also special. So the recurrence constructs a valid increment.
The recursion terminates because transformed values are roughly divided by . The only self-loop case is all ones, handled by the base case .
Implementation details:
Scan the current vector. If residues modulo differ, return infinity. Otherwise bucket numbers by ((x-c)/6) mod 7, which is their residue class among the seven possible multiples of modulo . For each bucket, compute the corresponding , transform only that bucket by dividing (x+k_r)/42, recurse, and minimize.
Complexity: each recursion level partitions the elements, and values shrink by a factor of about . The time is over a test case, with ; here the depth is tiny for . Memory is with these simple vectors, still easily inside limits.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const ll INF = numeric_limits<ll>::max() / 4;
ll dfs(const vector<ll>& a) {
if (a.empty()) return 0;
int rem = int(a[0] % 6);
ll mx = 0;
array<vector<ll>, 7> bucket;
for (ll x : a) {
mx = max(mx, x);
if (x % 6 != rem) return INF;
int id = int(((x - rem) / 6) % 7);
bucket[id].push_back(x);
}
if (mx == 1) return 5;
ll best = INF;
for (int r = 0; r < 7; ++r) {
ll add = (42 - rem - 6LL * r) % 42;
vector<ll> next;
next.reserve(bucket[r].size());
for (ll x : bucket[r]) {
next.push_back((x + add) / 42);
}
ll sub = dfs(next);
if (sub >= INF / 42) continue;
best = min(best, add + 42 * sub);
}
return best;
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<ll> a(n);
for (ll& x : a) cin >> x;
ll ans = dfs(a);
cout << (ans >= INF / 2 ? -1 : ans) << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
const ll INF = numeric_limits<ll>::max() / 4;
ll dfs(const vector<ll>& a) {
if (a.empty()) return 0;
int rem = int(a[0] % 6);
ll mx = 0;
array<vector<ll>, 7> bucket;
for (ll x : a) {
mx = max(mx, x);
if (x % 6 != rem) return INF;
int id = int(((x - rem) / 6) % 7);
bucket[id].push_back(x);
}
if (mx == 1) return 5;
ll best = INF;
for (int r = 0; r < 7; ++r) {
ll add = (42 - rem - 6LL * r) % 42;
vector<ll> next;
next.reserve(bucket[r].size());
for (ll x : bucket[r]) {
next.push_back((x + add) / 42);
}
ll sub = dfs(next);
if (sub >= INF / 42) continue;
best = min(best, add + 42 * sub);
}
return best;
}
int main() {
setIO();
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<ll> a(n);
for (ll& x : a) cin >> x;
ll ans = dfs(a);
cout << (ans >= INF / 2 ? -1 : ans) << '\n';
}
}