QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#503600#7613. Inverse ProblempandapythonerML 0ms3648kbC++238.2kb2024-08-03 20:44:302024-08-03 20:44:31

Judging History

你现在查看的是最新测评结果

  • [2024-08-03 20:44:31]
  • 评测
  • 测评结果:ML
  • 用时:0ms
  • 内存:3648kb
  • [2024-08-03 20:44:30]
  • 提交

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
...

result: