File size: 4,657 Bytes
1fd0050 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | #include <bits/stdc++.h>
using namespace std;
struct Instr {
enum Type { POP, HALT } type;
int a = 1, b = 1;
int x = 0, y = 0; // label indices (0-based)
bool set = false;
};
static const int NEVER = 1024; // never pushed
static const int TEMP = 1023; // pushed/popped as temporary
vector<Instr> prog;
int nextMarker = 1;
int newLabel() {
prog.push_back(Instr());
return (int)prog.size() - 1;
}
void setPOP(int lbl, int a, int x, int b, int y) {
auto &ins = prog[lbl];
ins.type = Instr::POP;
ins.a = a;
ins.x = x;
ins.b = b;
ins.y = y;
ins.set = true;
}
void setHALT(int lbl, int b, int y) {
auto &ins = prog[lbl];
ins.type = Instr::HALT;
ins.b = b;
ins.y = y;
ins.set = true;
}
struct Proc {
int m0, m1;
int entry;
};
Proc build(long long K, int cont0, int cont1) {
Proc p;
p.m0 = nextMarker++;
p.m1 = nextMarker++;
// Return dispatcher start label
int ret_check = newLabel();
if (K <= 9) {
int m = (int)((K - 3) / 2); // dummy pairs
if (m == 0) {
p.entry = ret_check;
} else {
p.entry = newLabel();
int cur = p.entry;
for (int i = 0; i < m; i++) {
int popLbl = newLabel();
setPOP(cur, NEVER, cur, TEMP, popLbl); // unconditional push TEMP -> popLbl
int nxt = (i == m - 1) ? ret_check : newLabel();
setPOP(popLbl, TEMP, nxt, TEMP, nxt); // pop TEMP -> nxt
cur = nxt;
}
}
} else {
bool extra = (K % 4 == 1); // need +7 version
long long u = extra ? (K - 7) / 2 : (K - 5) / 2;
int entry = newLabel();
int after1 = newLabel();
int after2;
if (extra) after2 = newLabel();
else after2 = ret_check;
// Build sub with continuations in parent
Proc sub = build(u, after1, after2);
// Call sub twice
setPOP(entry, NEVER, entry, sub.m0, sub.entry);
setPOP(after1, NEVER, after1, sub.m1, sub.entry);
// Optional extra dummy pair after second call
if (extra) {
int popTemp = newLabel();
setPOP(after2, NEVER, after2, TEMP, popTemp); // push TEMP
setPOP(popTemp, TEMP, ret_check, TEMP, ret_check); // pop TEMP -> ret_check
}
p.entry = entry;
}
// Return dispatcher: uniform 3 steps for marker0 or marker1
int dummyPush = newLabel();
int dummyPop = newLabel();
int failPop = newLabel();
int check1 = newLabel();
setPOP(ret_check, p.m0, dummyPush, p.m0, failPop);
setPOP(dummyPush, NEVER, dummyPush, TEMP, dummyPop); // unconditional push TEMP
setPOP(dummyPop, TEMP, cont0, TEMP, cont0); // pop TEMP -> cont0
setPOP(failPop, p.m0, check1, p.m0, check1); // pop the pushed m0
setPOP(check1, p.m1, cont1, p.m1, cont1); // pop m1 -> cont1
return p;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
long long k;
cin >> k;
if (k == 1) {
cout << 1 << "\n";
cout << "HALT PUSH 1 GOTO 1\n";
return 0;
}
if (k == 3) {
cout << 3 << "\n";
cout << "POP 1 GOTO 1 PUSH 1 GOTO 2\n";
cout << "POP 1 GOTO 3 PUSH 1 GOTO 2\n";
cout << "HALT PUSH 1 GOTO 3\n";
return 0;
}
// General case: k >= 5, odd
long long K = k - 2; // length of root procedure
prog.clear();
nextMarker = 1;
int start = newLabel();
int haltLbl = newLabel();
setHALT(haltLbl, 1, haltLbl);
Proc root = build(K, haltLbl, haltLbl);
setPOP(start, NEVER, start, root.m0, root.entry);
// Validate all instructions set
for (int i = 0; i < (int)prog.size(); i++) {
if (!prog[i].set) {
// Fill unreachable/unset with a harmless self-loop HALT (won't be reached)
setHALT(i, 1, i);
}
}
int n = (int)prog.size();
if (n > 512) {
// Should not happen, but ensure valid output.
// Fallback to simplest (won't be correct for judge, but constraints guarantee existence).
n = 1;
prog.assign(1, Instr());
setHALT(0, 1, 0);
}
cout << n << "\n";
for (int i = 0; i < n; i++) {
const auto &ins = prog[i];
if (ins.type == Instr::HALT) {
cout << "HALT PUSH " << ins.b << " GOTO " << (ins.y + 1) << "\n";
} else {
cout << "POP " << ins.a << " GOTO " << (ins.x + 1)
<< " PUSH " << ins.b << " GOTO " << (ins.y + 1) << "\n";
}
}
return 0;
} |