Submission details
Task:Ohjelmat
Sender:jhuun
Submission time:2025-10-19 22:12:39 +0300
Language:text
Status:READY
Result:0
Feedback
groupverdictscore
#10
Test results
testverdicttimescore
#10.00 s0details

Code

#include <bits/stdc++.h>

#define VERBOSE     0

#define PLUS        S[si - 1] += S[si], --si, OP.push_back("+")
#define MULTIPLY    S[si - 1] *= S[si], --si, OP.push_back("*")
#define SWAP        std::swap(S[si], S[si - 1]), OP.push_back("SWAP")
#define DUP         S[si + 1] = S[si], ++si, OP.push_back("DUP")
#define OVER        S[si + 1] = S[si - 1], ++si, OP.push_back("OVER")
#define ROT         std::swap(S[si], S[si - 2]), std::swap(S[si - 1], S[si - 2]), OP.push_back("ROT")
#define DROP        --si, OP.push_back("DROP")

#define MSBL(x_)    (uint64_t{1} << (uint64_t{64} - std::countl_zero<uint64_t>(x_) - 1))

uint64_t S[10000];
auto si = 0;
std::vector<std::string> OP;

// Jump assumptions:
// - Stack is [L, 2] when entering

void make_jump2() {
    DUP;      // [.., 2, 2]
    MULTIPLY; // [.., 4]
}

void make_jump3() {
    DUP;               // [.., 2, 2]
    make_jump2();      // [.., 2, 4]
    MULTIPLY;          // [.., 8]
}

void make_jump4() {
    make_jump2();      // [.., 4]
    DUP;               // [.., 4, 4]
    MULTIPLY;          // [.., 16]
}

void make_jump5() {
    DUP;               // [.., 2, 2]
    make_jump4();      // [.., 2, 16]
    MULTIPLY;          // [.., 32]
}

void make_jump6() {
    make_jump3();      // [.., 8]
    DUP;               // [.., 8, 8]
    MULTIPLY;          // [.., 64]
}

void make_jump7() {
    DUP;               // [.., 2, 2]
    make_jump6();      // [.., 2, 64]
    MULTIPLY;          // [.., 128]
}

void make_jump8() {
    make_jump4();      // [.., 16]
    DUP;               // [.., 16, 16]
    MULTIPLY;          // [.., 256]
}

void make_jump9() {
    DUP;               // [.., 2, 2]
    make_jump8();      // [.., 2, 256]
    MULTIPLY;          // [.., 512]
}

void make_jump10() {
    make_jump5();      // [.., 32]
    DUP;               // [.., 32, 32]
    MULTIPLY;          // [.., 1024]
}

void make_jump11() {
    DUP;                // [.., 2, 2]
    make_jump10();      // [.., 2, 1024]
    MULTIPLY;           // [.., 2048]
}

void make_jump12() {
    make_jump6();      // [.., 64]
    DUP;               // [.., 64, 64]
    MULTIPLY;          // [.., 4096]
}

void make_jump13() {
    DUP;                // [.., 2, 2]
    make_jump12();      // [.., 2, 4096]
    MULTIPLY;           // [.., 8192]
}

void make_jump14() {
    make_jump7();      // [.., 128]
    DUP;               // [.., 128, 128]
    MULTIPLY;          // [.., 16384]
}

void make_jump15() {
    make_jump5();      // [.., 32]
    DUP;               // [.., 32, 32]
    DUP;               // [.., 32, 32, 32]
    MULTIPLY;          // [.., 32, 1024]
    MULTIPLY;          // [.., 32768]
}

void make_jump16() {
    make_jump8();      // [.., 256]
    DUP;               // [.., 256, 256]
    MULTIPLY;          // [.., 65536]
}

void make_jump17() {
    DUP;                // [.., 2, 2]
    make_jump16();      // [.., 2, 65536]
    MULTIPLY;           // [.., 131072]
}

void make_jump18() {
    make_jump9();      // [.., 512]
    DUP;               // [.., 512, 512]
    MULTIPLY;          // [.., 262144]
}

void make_jump19() {
    DUP;                // [.., 2, 2]
    make_jump18();      // [.., 2, 262144]
    MULTIPLY;           // [.., 524288]
}

void print_stack() {
    if (VERBOSE) {
        for (int i = 0; i <= si; ++i) {
            std::cout << S[i] << ' ';
        }
        std::cout << '\n';
    }
}

// Enter with [2, L]
// - go to jmp with [L, 2]
// - retain=false:  [L, jmp]
// - retain=true:   [2, L, jmp] 
void jump(int j, bool retain) {
    if (retain) {
        OVER; // [2, L, 2]
    } else {
        SWAP; // [L, 2]
    }
    switch(j) {
        case 2:  { make_jump2();  break; }
        case 3:  { make_jump3();  break; }
        case 4:  { make_jump4();  break; }
        case 5:  { make_jump5();  break; }
        case 6:  { make_jump6();  break; }
        case 7:  { make_jump7();  break; }
        case 8:  { make_jump8();  break; }
        case 9:  { make_jump9();  break; }
        case 10: { make_jump10(); break; }
        case 11: { make_jump11(); break; }
        case 12: { make_jump12(); break; }
        case 13: { make_jump13(); break; }
        case 14: { make_jump14(); break; }
        case 15: { make_jump15(); break; }
        case 16: { make_jump16(); break; }
        case 17: { make_jump17(); break; }
        case 18: { make_jump18(); break; }
        case 19: { make_jump19(); break; }
        default: break;
    }
}

struct Number {
    uint64_t x;
    uint64_t L;
    std::vector<int> jumps;

    Number(uint64_t x_) {
        x = x_;
        L = MSBL(x_);
        std::vector<int> ones;
        for (uint64_t b = 4, i = 2; b <= L; b <<= 1, ++i) {
            if (x & b) ones.push_back(i);
        }
        int i = 1;
        for (auto o : ones) {
            jumps.push_back(o - i);
            i = o;
        }
    }
};

#define PREV3(OP1_, OP2_, OP3_) (OP[i - 2] == OP1_ && OP[i - 1] == OP2_ && OP[i] == OP3_)
#define PREV5(OP1_, OP2_, OP3_, OP4_, OP5_) (OP[i - 4] == OP1_ && OP[i - 3] == OP2_ && PREV3(OP3_, OP4_, OP5_))
#define POP(cnt_) int cnt__ = cnt_; do { OP_new.pop_back(); } while (cnt__--)

bool fix() {
    bool fixed = false;
    std::vector<std::string> OP_new = {OP[0], OP[1]};
    auto sz = OP.size();
    for (std::size_t i = 2; i < sz; ++i) {
        OP_new.push_back(OP[i]);
        // SWAP OVER SWAP => DUP OVER
        if (PREV3("SWAP", "OVER", "SWAP")) {
            POP(3);
            OP_new.push_back("DUP");
            OP_new.push_back("OVER");
            fixed = true;
        }
        // DUP SWAP OVER => DUP DUP
        if (PREV3("DUP", "SWAP", "OVER")) {
            POP(2);
            OP_new.push_back("DUP");
            fixed = true;
        }
        // OVER OVER DUP * * => DUP * OVER *
        if (i >= 4 && PREV5("OVER", "OVER", "DUP", "*", "*")) {
            POP(5);
            OP_new.push_back("DUP");
            OP_new.push_back("*");
            OP_new.push_back("OVER");
            OP_new.push_back("*");
        }
    }
    OP = OP_new;
    return fixed;
}

// Stack assumption when building normally:
// - [2, L], where L is current 1 << b

int main() {
    int t;
    std::cin >> t;
    for (int i = 0; i < t; ++i) {
        si = 0;
        S[0] = 1;
        OP.clear();
        uint64_t x;
        std::cin >> x;
        assert(x >= 4);
        if (VERBOSE) std::cout << "Solving: " << x << '\n';
        Number n(x);
        if (VERBOSE) {
            for (auto i = 1, bi = 1; i < 20; ++i, bi <<= 1) {
                std::cout << ((x & bi) ? 1 : 0);
            }
            std::cout << '\n';
            std::cout << "JUMPS:";
            for (const auto jmp : n.jumps) std::cout << " " << jmp;
            std::cout << '\n';
        }
        if (x & 1) {
            DUP; // [1, 1]
        }
        DUP; // [1, 1, 1] or [1, 1]
        PLUS; // [1, 2] or [2]
        DUP;  // [1, 2, 2] or [2, 2]
        print_stack();

        for (std::size_t j = 0; j < n.jumps.size(); ++j) {
            auto jmp = n.jumps[j];
            // Keep current one:
            if (j > 0 || (x & 2)) {
                SWAP; // [.., L, 2]
                OVER; // [.., L, 2, L]
            }
            const auto retain = j != n.jumps.size() - 1;
            if (jmp == 1) {
                if (retain) {
                    OVER;     // [.., L, 2, L, 2];
                }
                MULTIPLY; // [.., L, 2?, L * 2]
            } else {
                jump(jmp, retain); // [L, 2?, L, jmp]
                MULTIPLY;          // [L, 2?, L * jmp]
            }
            print_stack();
        }

        while (si > 0) {
            PLUS;
            print_stack();
        }

        assert(si == 0);
        assert(S[0] == x);

        while (fix()) { };

        std::cout << OP.size() << '\n';
        for (const auto& op : OP) {
            std::cout << op << ' ';
        }
        std::cout << '\n';
    }
}

Test details

Test 1

Verdict:

input
100
156798
300372
911450
236249
...

correct output
21
20
23
22
24
...

user output
#include <bits/stdc++.h>

#define VERBOSE     0

#define PLUS        S[si - 1] ...