| #include <iostream> |
| #include <vector> |
| #include <string> |
|
|
| using namespace std; |
|
|
| typedef long long ll; |
|
|
| struct Instruction { |
| string type; |
| int a; |
| int x; |
| int b; |
| int y; |
| }; |
|
|
| vector<Instruction> program; |
|
|
| |
| void add_inst(string type, int a, int x, int b = 0, int y = 0) { |
| Instruction inst; |
| inst.type = type; |
| inst.a = a; |
| inst.x = x; |
| inst.b = b; |
| inst.y = y; |
| program.push_back(inst); |
| } |
|
|
| int main() { |
| |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
|
|
| ll k; |
| if (!(cin >> k)) return 0; |
|
|
| |
| |
| if (k < 300) { |
| if (k == 1) { |
| cout << "1\nHALT PUSH 1 GOTO 1" << endl; |
| return 0; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| add_inst("POP", 1000, 2, 1, 2); |
| |
| ll pairs = (k - 3) / 2; |
| int next_addr = 2; |
| for (int i = 0; i < pairs; ++i) { |
| |
| add_inst("POP", 1000, next_addr + 1, 2, next_addr + 1); |
| |
| add_inst("POP", 2, next_addr + 2, 1, next_addr + 2); |
| next_addr += 2; |
| } |
| |
| |
| add_inst("POP", 1, next_addr + 1, 1, next_addr + 1); |
| |
| |
| add_inst("HALT", 1, next_addr + 1, 0, 0); |
| |
| cout << program.size() << endl; |
| for (const auto& inst : program) { |
| if (inst.type == "HALT") { |
| cout << "HALT PUSH " << inst.a << " GOTO " << inst.x << endl; |
| } else { |
| cout << "POP " << inst.a << " GOTO " << inst.x << " PUSH " << inst.b << " GOTO " << inst.y << endl; |
| } |
| } |
| return 0; |
| } |
|
|
| |
| |
| |
| |
| int M = 30; |
| vector<ll> G(M + 1); |
| |
| |
| |
| |
| G[1] = 2LL * M - 1; |
| for (int v = 2; v <= M; ++v) { |
| |
| |
| |
| |
| G[v] = (2LL * M - 2LL * v + 3) + 2LL * G[v - 1]; |
| } |
| |
| |
| |
| |
| |
| |
| ll target = k - (2LL * M + 1); |
| vector<int> u; |
| |
| |
| while (true) { |
| int best_v = -1; |
| |
| for (int v = M; v >= 1; --v) { |
| if (G[v] + 1 <= target) { |
| best_v = v; |
| break; |
| } |
| } |
| if (best_v == -1) break; |
| |
| u.push_back(best_v); |
| target -= (G[best_v] + 1); |
| } |
| |
| |
| |
| |
| |
| |
| |
| ll burn_pairs = target / 2; |
| |
| |
| |
| |
| int current_line = 1; |
| for (int i = 0; i < burn_pairs; ++i) { |
| |
| |
| |
| add_inst("POP", 1000, current_line + 1, 1000, current_line + 1); |
| add_inst("POP", 1000, current_line + 2, 1, current_line + 2); |
| current_line += 2; |
| } |
| |
| |
| int load_count = u.size(); |
| int loop_start = current_line + load_count; |
| |
| for (int i = 0; i < load_count; ++i) { |
| int val = u[i]; |
| int next_addr = (i == load_count - 1) ? loop_start : current_line + 1; |
| |
| add_inst("POP", 1000, next_addr, val, next_addr); |
| current_line++; |
| } |
| |
| |
| |
| struct BlockAddr { |
| int check; |
| int fail; |
| int expand; |
| int p2; |
| }; |
| vector<BlockAddr> blocks(M + 1); |
| int addr = loop_start; |
| |
| |
| blocks[M].check = addr; |
| |
| for (int v = M; v >= 2; --v) { |
| blocks[v].check = addr; |
| blocks[v].fail = addr + 1; |
| blocks[v].expand = addr + 2; |
| blocks[v].p2 = addr + 3; |
| addr += 4; |
| } |
| |
| blocks[1].check = addr; |
| blocks[1].fail = addr + 1; |
| addr += 2; |
| |
| int halt_addr = addr; |
| |
| |
| for (int v = M; v >= 2; --v) { |
| |
| add_inst("POP", v, blocks[v].expand, v, blocks[v].fail); |
| |
| |
| int next_check = blocks[v-1].check; |
| add_inst("POP", v, next_check, 1, next_check); |
| |
| |
| add_inst("POP", 1000, blocks[v].p2, v - 1, blocks[v].p2); |
| |
| |
| add_inst("POP", 1000, blocks[M].check, v - 1, blocks[M].check); |
| } |
| |
| |
| |
| add_inst("POP", 1, blocks[M].check, 1, blocks[1].fail); |
| |
| |
| add_inst("POP", 1, halt_addr, 1, halt_addr); |
| |
| |
| add_inst("HALT", 999, halt_addr, 0, 0); |
| |
| |
| cout << program.size() << endl; |
| for (const auto& inst : program) { |
| if (inst.type == "HALT") { |
| cout << "HALT PUSH " << inst.a << " GOTO " << inst.x << endl; |
| } else { |
| cout << "POP " << inst.a << " GOTO " << inst.x << " PUSH " << inst.b << " GOTO " << inst.y << endl; |
| } |
| } |
|
|
| return 0; |
| } |