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.
Ignore the absurd tree size. Since is tiny, only the finite boundary around the root matters. A direct firing is basically placing a cut on some node.
If you directly fire a node on day , then by the end it has regrown for hiring stages. So, if nobody cuts inside it later, it contributes working students.
To finish with finitely many working students, every infinite path downward must hit a directly fired node. These fired nodes become the leaves of a finite full binary tree.
If there are direct firings, the full binary tree above them has internal nodes. If leaf is fired with , then , so .
Now minimize the number of powers of two, each at most , that sum to . Then count Catalan tree shapes times the number of ways to assign those powers to the fired leaves.
Let .
The infinite tree is mostly psychological warfare. The actual problem is finite: choose a boundary of cuts near the root, and decide on which day each cut happens.
What One Firing Does
Suppose node is directly fired on day .
After that firing, the whole subtree of is gone. On later days, hiring grows it back from the top, one level per day. So by the end:
Write . Then a fired node contributes , where .
Also, once a subtree has been fired, you cannot later cut inside it. Those students were already fired indirectly. When they come back, firing them again is illegal. No double-dipping, no funny business.
The Fired Nodes Are A Boundary
To end with exactly finite , every infinite downward path must be cut somewhere. Otherwise infinitely many workers survive on that path's branch, which is very much not .
The directly fired nodes therefore form an antichain covering all infinite paths. Equivalently, they are the leaves of a finite full binary tree rooted at student .
If there are direct firings, this full binary tree has:
For fired leaf , let . Then the final number of active students is
.
The annoying terms cancel beautifully:
.
So each direct firing is just one power of two in a representation of , and the largest allowed power is .
Minimizing Direct Firings
We need the fewest powers of two from
that sum to .
Greedy is optimal: use the largest allowed power as much as possible, then use the binary representation of the remainder.
Let:
The unique minimal multiset is:
Thus
.
Counting
Now count strategies with this minimal .
First choose the boundary shape. A full ordered binary tree with leaves is counted by
.
Second assign the chosen exponents to the leaves. The largest powers are identical. All smaller powers are distinct because they come from binary set bits. So the number of assignments is
.
Therefore the answer is
.
Use
.
Since , factorials up to about are enough. The infinite tree was just a very dramatic way to ask for Catalan numbers and binary representation. Classic Codeforces nonsense, honestly.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1000000007LL;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll modPow(ll a, ll e) {
ll r = 1;
while (e > 0) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
int main() {
setIO();
int T;
cin >> T;
vector<pair<ll, int>> tests(T);
int maxK = 0;
for (auto &[n, k] : tests) {
cin >> n >> k;
maxK = max(maxK, k);
}
int LIM = 2 * maxK + 10;
vector<ll> fact(LIM + 1), invFact(LIM + 1), inv(LIM + 1);
fact[0] = 1;
for (int i = 1; i <= LIM; i++) fact[i] = fact[i - 1] * i % MOD;
invFact[LIM] = modPow(fact[LIM], MOD - 2);
for (int i = LIM; i >= 1; i--) invFact[i - 1] = invFact[i] * i % MOD;
inv[1] = 1;
for (int i = 2; i <= LIM; i++) {
inv[i] = MOD - (MOD / i) * inv[MOD % i] % MOD;
}
auto C = [&](int n, int r) -> ll {
if (r < 0 || r > n) return 0;
return fact[n] * invFact[r] % MOD * invFact[n - r] % MOD;
};
auto catalan = [&](int m) -> ll {
return C(2 * m, m) * inv[m + 1] % MOD;
};
for (auto [n, k] : tests) {
ll N = (ll)k + 1;
int lg = 63 - __builtin_clzll(N);
int b = (int)min<ll>(n - 1, lg);
ll p = 1LL << b;
ll q = N / p;
ll rem = N % p;
int L = (int)q + __builtin_popcountll(rem);
ll ans = catalan(L - 1);
ans = ans * fact[L] % MOD * invFact[q] % MOD;
cout << ans << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll MOD = 1000000007LL;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
ll modPow(ll a, ll e) {
ll r = 1;
while (e > 0) {
if (e & 1) r = r * a % MOD;
a = a * a % MOD;
e >>= 1;
}
return r;
}
int main() {
setIO();
int T;
cin >> T;
vector<pair<ll, int>> tests(T);
int maxK = 0;
for (auto &[n, k] : tests) {
cin >> n >> k;
maxK = max(maxK, k);
}
int LIM = 2 * maxK + 10;
vector<ll> fact(LIM + 1), invFact(LIM + 1), inv(LIM + 1);
fact[0] = 1;
for (int i = 1; i <= LIM; i++) fact[i] = fact[i - 1] * i % MOD;
invFact[LIM] = modPow(fact[LIM], MOD - 2);
for (int i = LIM; i >= 1; i--) invFact[i - 1] = invFact[i] * i % MOD;
inv[1] = 1;
for (int i = 2; i <= LIM; i++) {
inv[i] = MOD - (MOD / i) * inv[MOD % i] % MOD;
}
auto C = [&](int n, int r) -> ll {
if (r < 0 || r > n) return 0;
return fact[n] * invFact[r] % MOD * invFact[n - r] % MOD;
};
auto catalan = [&](int m) -> ll {
return C(2 * m, m) * inv[m + 1] % MOD;
};
for (auto [n, k] : tests) {
ll N = (ll)k + 1;
int lg = 63 - __builtin_clzll(N);
int b = (int)min<ll>(n - 1, lg);
ll p = 1LL << b;
ll q = N / p;
ll rem = N % p;
int L = (int)q + __builtin_popcountll(rem);
ll ans = catalan(L - 1);
ans = ans * fact[L] % MOD * invFact[q] % MOD;
cout << ans << '\n';
}
return 0;
}