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.
Try fixing the number of double-all operations first. Once you decide there are exactly doublings, their relative order is basically just gaps where single-index increments can live.
With doublings, index starts by contributing to the final value. So you only need to build
If any , that is impossible. No magic, no vibes, just overshoot.
An increment placed with future doublings contributes to the final value. For fixed , minimizing increments means representing using coins with as few coins as possible.
For powers of two, the optimal representation is unique:
So the increment count is
Try every feasible and take the minimum.
Counting is gap-by-gap. If increments of index must be placed in the gap with future doublings, that gap contributes
Here is the -th bit of for , and for . Since the modulo is and every individual , this multinomial is whenever ; otherwise use factorials and inverse factorials.
We need minimize operations and count optimal operation sequences. The trick is to stop thinking about the operation order first. Pick the number of doublings, then everything becomes binary bookkeeping.
Fix the number of doublings
Suppose the sequence uses exactly double-all operations.
Every original value gets doubled times, so before considering increments it contributes
to the final value. Therefore index still needs
extra value.
If some , then is impossible, because we already overshot . There is no undo button.
Since , we only need to try or so. Tiny.
How many increments are needed for fixed ?
An increment may happen:
So for index , we must write as a sum of coins
using as few coins as possible.
For powers of two, the greedy choice is optimal: use as many coins as possible, then use the binary representation of the remainder. Thus
So the total operation count for this is
Try every feasible , take the minimum value .
The representation is unique
This matters for counting.
For , the number of increments of index that contribute is exactly the -th bit of .
For , the number is
Why unique? If you had two coins for , you could replace them with one coin and use fewer increments. So below the top coin, every count must be or . The top coin can appear many times because there is no bigger allowed coin.
Counting operation sequences
The doublings split the sequence into gaps:
The gap with future doublings contains exactly the increments that contribute .
Let
be the required number of increments of index in that gap, and let
Inside that gap, the only freedom is the order of increment indices. Therefore the number of ways for that gap is the multinomial
The total number of sequences for this is the product over all gaps:
The double operations themselves are fixed separators, so they do not add another factorial. Do not count random placements of doubles separately; the gaps already encode exactly where they are. Counting them again would be classic off-by-a-whole-combinatorics-problem nonsense.
Modulo issue
The modulo is
which is prime.
Every individual is less than , because all values are at most . However, the sum can be much larger than .
Since every , none of the denominator factorials contains a factor of . If , then does contain a factor of , so the whole multinomial is modulo . If , we use the normal factorial formula.
So we precompute factorials and inverse factorials modulo . For a gap:
For , each is only or , so the denominator is irrelevant. Only the top gap needs real denominator work.
Algorithm
For each test case:
Try all from while feasible.
Compute
If any , skip this .
Compute operation count
Compute the number of optimal sequences for this fixed using gap multinomials.
Keep the minimum operation count; if multiple tie, add their counts modulo .
Complexity:
per test case in practice, since there are only about possible values of . Across all tests, this is easily fine.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 1000003;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll modpow(ll a, ll e) {
ll r = 1;
while (e) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
int main() {
setIO();
vector<ll> fact(MOD), invfact(MOD);
fact[0] = 1;
for (int i = 1; i < MOD; i++) fact[i] = fact[i - 1] * i % MOD;
invfact[MOD - 1] = modpow(fact[MOD - 1], MOD - 2);
for (int i = MOD - 2; i >= 0; i--) invfact[i] = invfact[i + 1] * (i + 1) % MOD;
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<int> a(n), b(n);
for (int &x : a) cin >> x;
for (int &x : b) cin >> x;
ll best = LLONG_MAX;
ll answer = 0;
for (int k = 0; k <= 20; k++) {
ll pw = 1LL << k;
bool ok = true;
ll ops = k;
vector<int> bitSum(k, 0);
ll topSum = 0;
ll topDen = 1;
for (int i = 0; i < n; i++) {
ll base = 1LL * a[i] * pw;
if (base > b[i]) {
ok = false;
break;
}
ll r = b[i] - base;
int rem = int(r % pw);
int top = int(r / pw);
topSum += top;
ops += top + __builtin_popcount((unsigned)rem);
for (int j = 0; j < k; j++) {
if ((rem >> j) & 1) bitSum[j]++;
}
topDen = topDen * invfact[top] % MOD;
}
if (!ok) continue;
ll ways = 1;
for (int j = 0; j < k; j++) {
ways = ways * fact[bitSum[j]] % MOD;
}
if (topSum >= MOD) {
ways = 0;
} else {
ways = ways * fact[(int)topSum] % MOD * topDen % MOD;
}
if (ops < best) {
best = ops;
answer = ways;
} else if (ops == best) {
answer += ways;
if (answer >= MOD) answer -= MOD;
}
}
cout << best << ' ' << answer % MOD << '\n';
}
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MOD = 1000003;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll modpow(ll a, ll e) {
ll r = 1;
while (e) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
int main() {
setIO();
vector<ll> fact(MOD), invfact(MOD);
fact[0] = 1;
for (int i = 1; i < MOD; i++) fact[i] = fact[i - 1] * i % MOD;
invfact[MOD - 1] = modpow(fact[MOD - 1], MOD - 2);
for (int i = MOD - 2; i >= 0; i--) invfact[i] = invfact[i + 1] * (i + 1) % MOD;
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<int> a(n), b(n);
for (int &x : a) cin >> x;
for (int &x : b) cin >> x;
ll best = LLONG_MAX;
ll answer = 0;
for (int k = 0; k <= 20; k++) {
ll pw = 1LL << k;
bool ok = true;
ll ops = k;
vector<int> bitSum(k, 0);
ll topSum = 0;
ll topDen = 1;
for (int i = 0; i < n; i++) {
ll base = 1LL * a[i] * pw;
if (base > b[i]) {
ok = false;
break;
}
ll r = b[i] - base;
int rem = int(r % pw);
int top = int(r / pw);
topSum += top;
ops += top + __builtin_popcount((unsigned)rem);
for (int j = 0; j < k; j++) {
if ((rem >> j) & 1) bitSum[j]++;
}
topDen = topDen * invfact[top] % MOD;
}
if (!ok) continue;
ll ways = 1;
for (int j = 0; j < k; j++) {
ways = ways * fact[bitSum[j]] % MOD;
}
if (topSum >= MOD) {
ways = 0;
} else {
ways = ways * fact[(int)topSum] % MOD * topDen % MOD;
}
if (ops < best) {
best = ops;
answer = ways;
} else if (ops == best) {
answer += ways;
if (answer >= MOD) answer -= MOD;
}
}
cout << best << ' ' << answer % MOD << '\n';
}
}