QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#503579 | #7613. Inverse Problem | pandapythoner | TL | 0ms | 10952kb | C++23 | 7.4kb | 2024-08-03 20:15:01 | 2024-08-03 20:15:01 |
Judging History
answer
#pragma GCC optimize("Ofast,unroll-loops,fast-math")
#include <ext/pb_ds/assoc_container.hpp>
#include <bits/stdc++.h>
using namespace std;
using namespace __gnu_pbds;
#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;
cc_hash_table<int, bool> dp_pref[maxn][maxn];
vector<ll> 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]);
int max_pref_sum = (n - 2) / 2.6;
int max_suff_sum = n - 2 - max_pref_sum - 1;
rep(x, n - 1) rep(y, n - 1) dp_suff[x][y].clear();
rep(x, n - 1) rep(y, n - 1) dp_pref[x][y].clear();
for (int val = 1; val <= n - 2; val += 1) {
dp_pref[val][0][factors[val]] = true;
for (int sum = 1; val + sum <= n - 2 and sum <= max_pref_sum; sum += 1) {
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][x * factors[val] % mod] = true;
}
}
}
}
auto restore_pref = [&](int val, int sum, ll x) {
assert(dp_pref[val][sum].find(x) != dp_pref[val][sum].end());
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 (dp_pref[old_val][sum - old_val].find(x) != dp_pref[old_val][sum - old_val].end()) {
new_val = old_val;
break;
}
}
assert(new_val != -1);
val = new_val;
sum -= val;
result.push_back(val);
}
return result;
};
for (int val = n - 2; val >= 1; val -= 1) {
dp_suff[val][0] = { 1 };
for (int sum = 1; val + sum <= n - 2 and sum <= max_suff_sum; sum += 1) {
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_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 (dp_pref[val][pref_sum].find(x) != dp_pref[val][pref_sum].end()) {
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
*/
詳細信息
Test #1:
score: 100
Accepted
time: 0ms
memory: 10952kb
input:
4 2 360 1 509949433
output:
2 1 2 5 3 1 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
Time Limit Exceeded
input:
9 185396120 468170792 837583517 696626231 338497514 762842660 800028852 928391161 733524004