답안 #1092871

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1092871 2024-09-25T09:24:57 Z Pannda Naan (JOI19_naan) C++17
29 / 100
4000 ms 4912 KB
#include <bits/stdc++.h>
using namespace std;

// base and base_digits must be consistent
const long long base = 1e9;
const int base_digits = 9;

struct bigint {
    vector<long long> a;
    int sign;

    bigint() :
        sign(1) {
    }

    bigint(long long v) {
        *this = v;
    }

    bigint(const string &s) {
        read(s);
    }

    void operator=(const bigint &v) {
        sign = v.sign;
        a = v.a;
    }

    void operator=(long long v) {
        sign = 1;
        if (v < 0)
            sign = -1, v = -v;
        for (; v > 0; v = v / base)
            a.push_back(v % base);
    }

    bigint operator+(const bigint &v) const {
        if (sign == v.sign) {
            bigint res = v;

            for (long long i = 0, carry = 0; i < (long long) max(a.size(), v.a.size()) || carry; ++i) {
                if (i == (long long) res.a.size())
                    res.a.push_back(0);
                res.a[i] += carry + (i < (long long) a.size() ? a[i] : 0);
                carry = res.a[i] >= base;
                if (carry)
                    res.a[i] -= base;
            }
            return res;
        }
        return *this - (-v);
    }

    bigint operator-(const bigint &v) const {
        if (sign == v.sign) {
            if (abs() >= v.abs()) {
                bigint res = *this;
                for (long long i = 0, carry = 0; i < (long long) v.a.size() || carry; ++i) {
                    res.a[i] -= carry + (i < (long long) v.a.size() ? v.a[i] : 0);
                    carry = res.a[i] < 0;
                    if (carry)
                        res.a[i] += base;
                }
                res.trim();
                return res;
            }
            return -(v - *this);
        }
        return *this + (-v);
    }

    void operator*=(long long v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (long long i = 0, carry = 0; i < (long long) a.size() || carry; ++i) {
            if (i == (long long) a.size())
                a.push_back(0);
            long long cur = a[i] * (long long) v + carry;
            carry = (long long) (cur / base);
            a[i] = (long long) (cur % base);
            //asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base));
        }
        trim();
    }

    bigint operator*(long long v) const {
        bigint res = *this;
        res *= v;
        return res;
    }

    friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) {
        long long norm = base / (b1.a.back() + 1);
        bigint a = a1.abs() * norm;
        bigint b = b1.abs() * norm;
        bigint q, r;
        q.a.resize(a.a.size());

        for (long long i = a.a.size() - 1; i >= 0; i--) {
            r *= base;
            r += a.a[i];
            long long s1 = r.a.size() <= b.a.size() ? 0 : r.a[b.a.size()];
            long long s2 = r.a.size() <= b.a.size() - 1 ? 0 : r.a[b.a.size() - 1];
            long long d = ((long long) base * s1 + s2) / b.a.back();
            r -= b * d;
            while (r < 0)
                r += b, --d;
            q.a[i] = d;
        }

        q.sign = a1.sign * b1.sign;
        r.sign = a1.sign;
        q.trim();
        r.trim();
        return make_pair(q, r / norm);
    }

    bigint operator/(const bigint &v) const {
        return divmod(*this, v).first;
    }

    bigint operator%(const bigint &v) const {
        return divmod(*this, v).second;
    }

    void operator/=(long long v) {
        if (v < 0)
            sign = -sign, v = -v;
        for (long long i = (long long) a.size() - 1, rem = 0; i >= 0; --i) {
            long long cur = a[i] + rem * (long long) base;
            a[i] = (long long) (cur / v);
            rem = (long long) (cur % v);
        }
        trim();
    }

    bigint operator/(long long v) const {
        bigint res = *this;
        res /= v;
        return res;
    }

    long long operator%(long long v) const {
        if (v < 0)
            v = -v;
        long long m = 0;
        for (long long i = a.size() - 1; i >= 0; --i)
            m = (a[i] + m * (long long) base) % v;
        return m * sign;
    }

    void operator+=(const bigint &v) {
        *this = *this + v;
    }
    void operator-=(const bigint &v) {
        *this = *this - v;
    }
    void operator*=(const bigint &v) {
        *this = *this * v;
    }
    void operator/=(const bigint &v) {
        *this = *this / v;
    }

    bool operator<(const bigint &v) const {
        if (sign != v.sign)
            return sign < v.sign;
        if (a.size() != v.a.size())
            return a.size() * sign < v.a.size() * v.sign;
        for (long long i = a.size() - 1; i >= 0; i--)
            if (a[i] != v.a[i])
                return a[i] * sign < v.a[i] * sign;
        return false;
    }

    bool operator>(const bigint &v) const {
        return v < *this;
    }
    bool operator<=(const bigint &v) const {
        return !(v < *this);
    }
    bool operator>=(const bigint &v) const {
        return !(*this < v);
    }
    bool operator==(const bigint &v) const {
        return !(*this < v) && !(v < *this);
    }
    bool operator!=(const bigint &v) const {
        return *this < v || v < *this;
    }

    void trim() {
        while (!a.empty() && !a.back())
            a.pop_back();
        if (a.empty())
            sign = 1;
    }

    bool isZero() const {
        return a.empty() || (a.size() == 1 && !a[0]);
    }

    bigint operator-() const {
        bigint res = *this;
        res.sign = -sign;
        return res;
    }

    bigint abs() const {
        bigint res = *this;
        res.sign *= res.sign;
        return res;
    }

    long long longValue() const {
        long long res = 0;
        for (long long i = a.size() - 1; i >= 0; i--)
            res = res * base + a[i];
        return res * sign;
    }

    friend bigint gcd(const bigint &a, const bigint &b) {
        return b.isZero() ? a : gcd(b, a % b);
    }
    friend bigint lcm(const bigint &a, const bigint &b) {
        return a / gcd(a, b) * b;
    }

    void read(const string &s) {
        sign = 1;
        a.clear();
        long long pos = 0;
        while (pos < (long long) s.size() && (s[pos] == '-' || s[pos] == '+')) {
            if (s[pos] == '-')
                sign = -sign;
            ++pos;
        }
        for (long long i = s.size() - 1; i >= pos; i -= base_digits) {
            long long x = 0;
            for (long long j = max(pos, i - base_digits + 1); j <= i; j++)
                x = x * 10 + s[j] - '0';
            a.push_back(x);
        }
        trim();
    }

    friend istream& operator>>(istream &stream, bigint &v) {
        string s;
        stream >> s;
        v.read(s);
        return stream;
    }

    friend ostream& operator<<(ostream &stream, const bigint &v) {
        if (v.sign == -1)
            stream << '-';
        stream << (v.a.empty() ? 0 : v.a.back());
        for (long long i = (long long) v.a.size() - 2; i >= 0; --i)
            stream << setw(base_digits) << setfill('0') << v.a[i];
        return stream;
    }

    static vector<long long> convert_base(const vector<long long> &a, long long old_digits, long long new_digits) {
        vector<long long> p(max(old_digits, new_digits) + 1);
        p[0] = 1;
        for (long long i = 1; i < (long long) p.size(); i++)
            p[i] = p[i - 1] * 10;
        vector<long long> res;
        long long cur = 0;
        long long cur_digits = 0;
        for (long long i = 0; i < (long long) a.size(); i++) {
            cur += a[i] * p[cur_digits];
            cur_digits += old_digits;
            while (cur_digits >= new_digits) {
                res.push_back((long long)(cur % p[new_digits]));
                cur /= p[new_digits];
                cur_digits -= new_digits;
            }
        }
        res.push_back((long long) cur);
        while (!res.empty() && !res.back())
            res.pop_back();
        return res;
    }

    typedef vector<long long> vll;

    static vll karatsubaMultiply(const vll &a, const vll &b) {
        long long n = a.size();
        vll res(n + n);
        if (n <= 32) {
            for (long long i = 0; i < n; i++)
                for (long long j = 0; j < n; j++)
                    res[i + j] += a[i] * b[j];
            return res;
        }

        long long k = n >> 1;
        vll a1(a.begin(), a.begin() + k);
        vll a2(a.begin() + k, a.end());
        vll b1(b.begin(), b.begin() + k);
        vll b2(b.begin() + k, b.end());

        vll a1b1 = karatsubaMultiply(a1, b1);
        vll a2b2 = karatsubaMultiply(a2, b2);

        for (long long i = 0; i < k; i++)
            a2[i] += a1[i];
        for (long long i = 0; i < k; i++)
            b2[i] += b1[i];

        vll r = karatsubaMultiply(a2, b2);
        for (long long i = 0; i < (long long) a1b1.size(); i++)
            r[i] -= a1b1[i];
        for (long long i = 0; i < (long long) a2b2.size(); i++)
            r[i] -= a2b2[i];

        for (long long i = 0; i < (long long) r.size(); i++)
            res[i + k] += r[i];
        for (long long i = 0; i < (long long) a1b1.size(); i++)
            res[i] += a1b1[i];
        for (long long i = 0; i < (long long) a2b2.size(); i++)
            res[i + n] += a2b2[i];
        return res;
    }

    bigint operator*(const bigint &v) const {
        vector<long long> a6 = convert_base(this->a, base_digits, 6);
        vector<long long> b6 = convert_base(v.a, base_digits, 6);
        vll a(a6.begin(), a6.end());
        vll b(b6.begin(), b6.end());
        while (a.size() < b.size())
            a.push_back(0);
        while (b.size() < a.size())
            b.push_back(0);
        while (a.size() & (a.size() - 1))
            a.push_back(0), b.push_back(0);
        vll c = karatsubaMultiply(a, b);
        bigint res;
        res.sign = sign * v.sign;
        for (long long i = 0, carry = 0; i < (long long) c.size(); i++) {
            long long cur = c[i] + carry;
            res.a.push_back((long long) (cur % 1000000));
            carry = (long long) (cur / 1000000);
        }
        res.a = convert_base(res.a, 6, base_digits);
        res.trim();
        return res;
    }
};

bigint mygcd(bigint a, bigint b) {
    if (b == 0) return a;
    return mygcd(b, a % b);
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    struct Fraction {
        bigint a = 0, b = 1;
        bool operator<(const Fraction &other) const & {
            return a * other.b < other.a * b;
        }
        bool operator<=(const Fraction &other) const & {
            return !(other < *this);
        }
        Fraction operator*(const Fraction &other) const & {
            bigint A = a * other.a;
            bigint B = b * other.b;
            return {A, B};
//            bigint G = __gcd(A, B);
//            return {A / G, B / G};
        }
        Fraction operator+(const Fraction &other) const & {
            bigint B = b * other.b;
            bigint A = a * other.b + other.a * b;
            return {A, B};
//            bigint G = abs(__gcd(A, B));
//            return {A / G, B / G};
        }
        Fraction operator-(Fraction other) {
            other.a *= -1;
            return (*this) + other;
        }
    };

    int n, m;
    cin >> n >> m;

    vector<vector<int>> v(n, vector<int>(m));
    vector<vector<int>> f(n, vector<int>(m + 1, 0));
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            int x;
            cin >> x;
            v[i][j] = x;
            f[i][j + 1] = f[i][j] + x;
        }
    }

    vector<Fraction> key;
    vector<int> perm;

    vector<bool> chosen(n, false);
    Fraction cur = {0, 1};
    vector<int> ptr(n, 0); // possible cut for i is in [ptr[i], ptr[i] + 1)

    for (int t = 0; t < n - 1; t++) {
//        cout << "Yo!" << endl;
        vector<pair<Fraction, int>> get = [&]() -> vector<pair<Fraction, int>> {
            vector<pair<Fraction, int>> res;
            for (int i = 0; i < n; i++) {
                if (chosen[i]) continue;
//                cout << "Ya!" << endl;
                Fraction nxt = [&]() -> Fraction {
                    auto F = [&](Fraction x) -> Fraction {
                        bigint get = x.a / x.b;
                        int j = get.a.size() == 0 ? 0 : get.a[0];
                        if (j < m) return Fraction{f[i][j], 1} + Fraction{v[i][j], 1} * Fraction{x.a % x.b, x.b};
                        return Fraction{f[i][m], 1};
                    };
                    Fraction req = F(Fraction{m, 1}) * Fraction{1, n};
                    while (true) {
                        if (F(Fraction{ptr[i] + 1, 1}) - F(cur) <= req) { // then is not enough
                            ptr[i]++;
                            continue;
                        }
                        Fraction rem = req + F(cur) - F(Fraction{ptr[i], 1});
                        return Fraction{ptr[i], 1} + rem * Fraction{1, v[i][ptr[i]]};
                    }
                }();
//                cout << "Ye!" << endl;
                res.push_back({nxt, i});
            }
            return res;
        }();
        auto [nxt, i] = *min_element(get.begin(), get.end());
        key.push_back(nxt);
        perm.push_back(i);
        cur = nxt;
        chosen[i] = true;
//        cout << nxt.a << ' ' << nxt.b << endl;
    }

    for (int i = 0; i < n; i++) {
        if (!chosen[i]) perm.push_back(i);
    }

    for (Fraction frac : key) {
        bigint g = gcd(frac.a, frac.b);
        cout << frac.a / g << ' ' << frac.b / g << '\n';
//        cout << frac.a << ' ' << frac.b << '\n';
    }
    for (int i : perm) {
        cout << i + 1 << ' ';
    }
    cout << '\n';
}
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 9 ms 348 KB Output is correct
3 Correct 10 ms 508 KB Output is correct
4 Correct 11 ms 348 KB Output is correct
5 Correct 6 ms 596 KB Output is correct
6 Correct 1 ms 348 KB Output is correct
7 Correct 7 ms 348 KB Output is correct
8 Correct 1 ms 348 KB Output is correct
9 Correct 3 ms 348 KB Output is correct
10 Correct 3 ms 348 KB Output is correct
11 Correct 11 ms 520 KB Output is correct
12 Correct 12 ms 516 KB Output is correct
13 Correct 11 ms 348 KB Output is correct
14 Correct 12 ms 344 KB Output is correct
15 Correct 15 ms 348 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 7 ms 344 KB Output is correct
2 Correct 17 ms 520 KB Output is correct
3 Correct 23 ms 528 KB Output is correct
4 Correct 33 ms 552 KB Output is correct
5 Correct 26 ms 348 KB Output is correct
6 Correct 16 ms 508 KB Output is correct
7 Correct 8 ms 348 KB Output is correct
8 Correct 10 ms 492 KB Output is correct
9 Correct 37 ms 348 KB Output is correct
10 Correct 35 ms 348 KB Output is correct
11 Correct 23 ms 348 KB Output is correct
12 Correct 2 ms 344 KB Output is correct
13 Correct 19 ms 516 KB Output is correct
14 Correct 35 ms 564 KB Output is correct
15 Correct 30 ms 348 KB Output is correct
16 Correct 38 ms 348 KB Output is correct
17 Correct 34 ms 344 KB Output is correct
18 Correct 47 ms 348 KB Output is correct
19 Correct 44 ms 344 KB Output is correct
20 Correct 35 ms 344 KB Output is correct
21 Correct 43 ms 344 KB Output is correct
22 Correct 43 ms 348 KB Output is correct
23 Correct 1 ms 348 KB Output is correct
24 Correct 32 ms 348 KB Output is correct
25 Correct 24 ms 348 KB Output is correct
26 Correct 10 ms 348 KB Output is correct
27 Correct 31 ms 548 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 344 KB Output is correct
2 Correct 9 ms 348 KB Output is correct
3 Correct 10 ms 508 KB Output is correct
4 Correct 11 ms 348 KB Output is correct
5 Correct 6 ms 596 KB Output is correct
6 Correct 1 ms 348 KB Output is correct
7 Correct 7 ms 348 KB Output is correct
8 Correct 1 ms 348 KB Output is correct
9 Correct 3 ms 348 KB Output is correct
10 Correct 3 ms 348 KB Output is correct
11 Correct 11 ms 520 KB Output is correct
12 Correct 12 ms 516 KB Output is correct
13 Correct 11 ms 348 KB Output is correct
14 Correct 12 ms 344 KB Output is correct
15 Correct 15 ms 348 KB Output is correct
16 Correct 7 ms 344 KB Output is correct
17 Correct 17 ms 520 KB Output is correct
18 Correct 23 ms 528 KB Output is correct
19 Correct 33 ms 552 KB Output is correct
20 Correct 26 ms 348 KB Output is correct
21 Correct 16 ms 508 KB Output is correct
22 Correct 8 ms 348 KB Output is correct
23 Correct 10 ms 492 KB Output is correct
24 Correct 37 ms 348 KB Output is correct
25 Correct 35 ms 348 KB Output is correct
26 Correct 23 ms 348 KB Output is correct
27 Correct 2 ms 344 KB Output is correct
28 Correct 19 ms 516 KB Output is correct
29 Correct 35 ms 564 KB Output is correct
30 Correct 30 ms 348 KB Output is correct
31 Correct 38 ms 348 KB Output is correct
32 Correct 34 ms 344 KB Output is correct
33 Correct 47 ms 348 KB Output is correct
34 Correct 44 ms 344 KB Output is correct
35 Correct 35 ms 344 KB Output is correct
36 Correct 43 ms 344 KB Output is correct
37 Correct 43 ms 348 KB Output is correct
38 Correct 1 ms 348 KB Output is correct
39 Correct 32 ms 348 KB Output is correct
40 Correct 24 ms 348 KB Output is correct
41 Correct 10 ms 348 KB Output is correct
42 Correct 31 ms 548 KB Output is correct
43 Execution timed out 4066 ms 4912 KB Time limit exceeded
44 Halted 0 ms 0 KB -