QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#503600 | #7613. Inverse Problem | pandapythoner | ML | 0ms | 3648kb | C++23 | 8.2kb | 2024-08-03 20:44:30 | 2024-08-03 20:44:31 |
Judging History
answer
#pragma GCC optimize("Ofast,unroll-loops,fast-math")
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define flt double
#define all(a) a.begin(), a.end()
#define rall(a) a.rbegin(), a.rend()
#define rep(i, n) for(int i = 0; i < n; i += 1)
#define len(a) ((int)(a).size())
const ll inf = 1e18;
mt19937 rnd(234);
const ll mod = 1e9 + 7;
ll bin_pow(ll x, ll n) {
ll rs = 1;
for (ll a = x, i = 1; i <= n; i *= 2, a = (a * a) % mod)
if (n & i) rs = rs * a % mod;
return rs;
}
ll inv(ll x) {
ll a = bin_pow(x, mod - 2);
assert(a * x % mod == 1);
return a;
}
vector<pair<int, int>> restore_tree(vector<int> degs) {
int n = len(degs);
vector<pair<int, int>> edges;
set<pair<int, int>> st;
int sum = 0;
rep(i, n) {
sum += degs[i];
st.insert(make_pair(degs[i], i));
}
assert(sum == 2 * n - 2);
while (!st.empty()) {
assert(len(st) >= 2);
auto [du, u] = *st.begin();
st.erase(st.begin());
auto [dv, v] = *prev(st.end());
st.erase(prev(st.end()));
assert(du == 1);
edges.push_back(make_pair(u, v));
assert(st.empty() or dv > 1);
if (dv > 1)
st.insert(make_pair(dv - 1, v));
}
return edges;
}
const int maxn = 200;
vector<ll> dp_pref[maxn][maxn], dp_suff[maxn][maxn];
int32_t main() {
if (1) {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
int t;
cin >> t;
vector<ll> a(t);
rep(i, t) cin >> a[i];
vector<bool> is_solved(t, false);
vector<vector<pair<int, int>>> trees(t);
rep(i, t) {
if (a[i] == 1) {
trees[i] = {};
is_solved[i] = true;
} else if (a[i] == 2) {
trees[i] = { make_pair(0, 1) };
is_solved[i] = true;
}
}
for (ll n = 3; ; n += 1) {
if (all_of(all(is_solved), identity())) {
break;
}
cerr << n << "\n";
assert(n < maxn);
vector<ll> factors(n - 1);
factors[0] = 1;
for (int i = 1; i <= n - 2; i += 1) {
factors[i] = (factors[i - 1] * (n - 1 - i)) % mod;
}
vector<ll> inv_factors(n - 1);
rep(i, n - 1) inv_factors[i] = inv(factors[i]);
rep(x, n - 1) rep(y, n - 1) dp_pref[x][y] = dp_suff[x][y] = {};
int max_pref_sum = 0;
int max_suff_sum = 0;
for (int val = 1; val <= n - 2; val += 1) {
dp_pref[val][0] = { factors[val] };
dp_suff[val][0] = { 1 };
}
while (max_pref_sum + max_suff_sum + 1 < n - 2) {
int mx_sz_pref = 0;
int mx_sz_suff = 0;
for (int val = 1; val <= n - 2; val += 1) mx_sz_pref = max(mx_sz_pref, len(dp_pref[val][max_pref_sum]));
for (int val = 1; val <= n - 2; val += 1) mx_sz_suff = max(mx_sz_suff, len(dp_suff[val][max_suff_sum]));
if (mx_sz_pref * 600 < mx_sz_suff) {
max_pref_sum += 1;
for (int val = 1; val <= n - 2; val += 1) {
int sum = max_pref_sum;
int sum_size = 0;
for (int old_val = 1; old_val <= sum and old_val <= val; old_val += 1) {
sum_size += len(dp_pref[old_val][sum - old_val]);
}
dp_pref[val][sum].reserve(sum_size);
for (int old_val = 1; old_val <= sum and old_val <= val; old_val += 1) {
for (auto x : dp_pref[old_val][sum - old_val]) {
dp_pref[val][sum].push_back(x * factors[val] % mod);
}
}
sort(all(dp_pref[val][sum]));
dp_pref[val][sum].resize(unique(all(dp_pref[val][sum])) - dp_pref[val][sum].begin());
}
} else {
max_suff_sum += 1;
for (int val = n - 2; val >= 1; val -= 1) {
int sum = max_suff_sum;
int sum_size = 0;
for (int old_val = val; old_val <= sum; old_val += 1) {
sum_size += len(dp_suff[old_val][sum - old_val]);
}
dp_suff[val][sum].reserve(sum_size);
for (int old_val = val; old_val <= sum; old_val += 1) {
for (auto x : dp_suff[old_val][sum - old_val]) {
dp_suff[val][sum].push_back(x * inv_factors[old_val] % mod);
}
}
// sort(all(dp_suff[val][sum]));
// dp_suff[val][sum].resize(unique(all(dp_suff[val][sum])) - dp_suff[val][sum].begin());
}
}
}
auto restore_pref = [&](int val, int sum, ll x) {
assert(binary_search(all(dp_pref[val][sum]), x));
vector<int> result;
result.push_back(val);
while (sum > 0) {
int new_val = -1;
x = x * inv_factors[val] % mod;
for (int old_val = 1; old_val <= sum and old_val <= val; old_val += 1) {
if (binary_search(all(dp_pref[old_val][sum - old_val]), x)) {
new_val = old_val;
break;
}
}
assert(new_val != -1);
val = new_val;
sum -= val;
result.push_back(val);
}
return result;
};
auto restore_suff = [&](int val, int sum, ll x) {
assert(find(all(dp_suff[val][sum]), x) != dp_suff[val][sum].end());
vector<int> result;
while (sum > 0) {
int new_val = -1;
for (int old_val = val; old_val <= sum; old_val += 1) {
if (find(all(dp_suff[old_val][sum - old_val]), x * factors[old_val] % mod) != dp_suff[old_val][sum - old_val].end()) {
new_val = old_val;
break;
}
}
assert(new_val != -1);
x = x * factors[new_val] % mod;
val = new_val;
sum -= val;
result.push_back(val);
}
return result;
};
ll d = n * (n - 1) % mod;
ll invd = inv(d);
for (int pref_sum = 0; pref_sum <= max_pref_sum; pref_sum += 1) {
for (int val = 1; pref_sum + val <= n - 2; val += 1) {
if (pref_sum + val <= max_pref_sum) continue;
int suff_sum = n - 2 - pref_sum - val;
assert(suff_sum <= max_suff_sum);
if (dp_pref[val][pref_sum].empty() or dp_suff[val][suff_sum].empty()) continue;
rep(i, t) if (!is_solved[i]) {
ll biba = a[i] * invd % mod;
for (auto y : dp_suff[val][suff_sum]) {
ll x = biba * y % mod;
if (binary_search(all(dp_pref[val][pref_sum]), x)) {
vector<int> degs_pref = restore_pref(val, pref_sum, x);
vector<int> degs_suff = restore_suff(val, suff_sum, y);
auto degs = degs_pref;
for (auto f : degs_suff) {
degs.push_back(f);
}
assert(len(degs) <= n - 2);
degs.resize(n, 0);
for (auto& f : degs) f += 1;
trees[i] = restore_tree(degs);
is_solved[i] = true;
break;
}
}
}
}
}
}
for (auto tree : trees) {
int n = len(tree) + 1;
cout << n << "\n";
for (auto [u, v] : tree) {
cout << u + 1 << " " << v + 1 << "\n";
}
}
return 0;
}
/*
9
185396120
468170792
837583517
696626231
338497514
762842660
800028852
928391161
733524004
*/
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3648kb
input:
4 2 360 1 509949433
output:
2 1 2 5 3 2 4 2 2 1 1 5 1 10 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 10
result:
ok OK (4 test cases)
Test #2:
score: -100
Memory Limit Exceeded
input:
9 185396120 468170792 837583517 696626231 338497514 762842660 800028852 928391161 733524004
output:
14 11 10 12 9 13 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 14 122 21 20 22 20 23 20 24 20 25 20 26 20 27 20 28 20 29 20 30 20 31 20 32 20 33 20 34 20 35 20 36 20 37 19 38 18 39 20 40 19 41 18 42 17 43 20 44 19 45 18 46 17 47 20 48 19 49 18 50 17 51 20 52 19 53 18 54 17 55 16 56 20 57 19 58 18 59 17 ...