Jump to content
Main menu
Main menu
move to sidebar
hide
Navigation
Main page
Recent changes
Random page
freem
Search
Search
Appearance
Create account
Log in
Personal tools
Create account
Log in
Pages for logged out editors
learn more
Contributions
Talk
Editing
Openai/69679fe4-9524-800d-9c74-5c34521fd378
(section)
Add languages
Page
Discussion
English
Read
Edit
Edit source
View history
Tools
Tools
move to sidebar
hide
Actions
Read
Edit
Edit source
View history
General
What links here
Related changes
Special pages
Page information
Appearance
move to sidebar
hide
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
=== Assistant: WA ๋ฌ ๊ฐ์ฅ ํํ ์์ธ์ ์ถ๋ ฅํ ๋จธ์ ์ ๋ ธ๋ ์ t๊ฐ 1,500,000์ ์ด๊ณผํด์ํน์ ๊ทธ์ ์คํ๊ฒ ์ปค์ ธ์ ๋จธ์ ์์ฒด๊ฐ โ์ ํจํ์ง ์์ ์ถ๋ ฅโ์ผ๋ก ํ์ ๋๋ ์ผ์ด์ค์ ๋๋ค. === WA ๋ฌ ๊ฐ์ฅ ํํ ์์ธ์ ์ถ๋ ฅํ ๋จธ์ ์ ๋ ธ๋ ์ <code>t</code>๊ฐ 1,500,000์ ์ด๊ณผํด์(ํน์ ๊ทธ์ ์คํ๊ฒ ์ปค์ ธ์) ๋จธ์ ์์ฒด๊ฐ โ์ ํจํ์ง ์์ ์ถ๋ ฅโ์ผ๋ก ํ์ ๋๋ ์ผ์ด์ค์ ๋๋ค. ์ ๊ฐ ์ด์ ์ ์ค ํํ์ฒ๋ผ == ๋น๊ต(EQ)๋ฅผ (XOR + NOT)๋ก ๋งค ๋นํธ๋ง๋ค ๋ง๋ค๊ณ , ๋ ์ ํ ๋ก์ง์์ MUX๋ฅผ ๋นํธ๋ง๋ค ํ์ด์ ๋ง๋ค๋ฉด, n=1000 ๊ทผ์ฒ์์ ๋ด๋ถ ๋ ธ๋๊ฐ ์ฝ๊ฒ 150๋ง์ ๋์ด๊ฐ๋๋ค โ ์ฑ์ ๊ธฐ์์ ๋ฐ๋ก WA. ์๋ ์ฝ๋๋ ๊ฐ์ ํ๋กํ ์ฝ(โ์ต์ ์ฐจ์ clique ์ ์ / ์ต๋ ์ฐจ์ independent ์ ์ โ์ผ๋ก S๋ฅผ ์ค์ด๊ณ , membership ๋นํธ๋ค์ OR ํด์ ์ต์ข ํ์ )์ ์ ์งํ๋, * x == v ๋น๊ต๋ฅผ ๋ฏธ๋ฆฌ NOT ๋นํธ๋ฅผ ๋ง๋ค์ด ๋๊ณ AND ์ฒด์ธ์ผ๋ก ์ฒ๋ฆฌ (๊ฒ์ดํธ ์ ๋ํญ ๊ฐ์) * ์ ํ ๊ฐฑ์ ์์ ๋นํธ๊ฐ 0/1์ธ ๊ฒฝ์ฐ๋ฅผ ์ด์ฉํด OR/AND 1๊ฐ๋ก ๊ฐฑ์ (MUX ํญ๋ฐ ๋ฐฉ์ง) * ๊ธฐ๋ณธ์ ์ธ ์์ ํด๋ฉ ์ ์ฉ ํด์ t๊ฐ ์์ ํ๊ฒ 150๋ง ์๋๋ก ๋ด๋ ค๊ฐ๋๋ก ์ต์ ํํ์ต๋๋ค. ์๋ ์์ฑ C++ ์ฝ๋ ๊ทธ๋๋ก ์ ์ถํ๋ฉด ๋ฉ๋๋ค. <syntaxhighlight lang="cpp">#include <bits/stdc++.h> #include <charconv> using namespace std; struct Node { int x, y; uint8_t f; // truth table code 0..15 (bit0=b(0,0)) }; struct FastOutput { static constexpr size_t FLUSH_THRESHOLD = 1u << 20; // 1MB string buf; FastOutput() { buf.reserve(FLUSH_THRESHOLD * 2); } inline void flush() { if (!buf.empty()) { cout.write(buf.data(), (streamsize)buf.size()); buf.clear(); } } inline void ensure() { if (buf.size() >= FLUSH_THRESHOLD) flush(); } inline void putChar(char c) { buf.push_back(c); ensure(); } inline void putStr(const char* s) { buf.append(s); ensure(); } inline void putInt(int v) { char tmp[32]; auto [ptr, ec] = to_chars(tmp, tmp + 32, v); (void)ec; buf.append(tmp, ptr - tmp); ensure(); } }; struct CircuitBuilder { int n, k; int L; // sources = n + 2k vector<Node> nodes; // internal nodes, id = L + index int const0, const1; // truth table codes static constexpr uint8_t F_AND = 8; // 0001 static constexpr uint8_t F_OR = 14; // 0111 static constexpr uint8_t F_XOR = 6; // 0110 static constexpr uint8_t F_NOTX = 3; // 1100 (negate first input) static constexpr uint8_t F_COPYX = 12; // 0011 (copy first input) CircuitBuilder(int n_, int k_, int reserveInternal = 0) : n(n_), k(k_) { L = n + 2 * k; nodes.reserve(reserveInternal > 0 ? reserveInternal : 1024); // const0 = x0 XOR x0 const0 = add_gate(0, 0, F_XOR); // const1 = NOT(const0) const1 = add_gate(const0, const0, F_NOTX); } inline int add_gate(int x, int y, uint8_t f) { nodes.push_back({x, y, f}); return L + (int)nodes.size() - 1; } // Constant-folding primitives inline int NOT(int a) { if (a == const0) return const1; if (a == const1) return const0; return add_gate(a, a, F_NOTX); } inline int AND(int a, int b) { if (a == const0 || b == const0) return const0; if (a == const1) return b; if (b == const1) return a; if (a == b) return a; return add_gate(a, b, F_AND); } inline int OR(int a, int b) { if (a == const1 || b == const1) return const1; if (a == const0) return b; if (b == const0) return a; if (a == b) return a; return add_gate(a, b, F_OR); } inline int XOR(int a, int b) { if (a == const0) return b; if (b == const0) return a; if (a == b) return const0; if (a == const1) return NOT(b); if (b == const1) return NOT(a); return add_gate(a, b, F_XOR); } inline int COPY(int a) { return add_gate(a, a, F_COPYX); } inline int MUX(int sel, int a, int b) { // sel ? a : b if (sel == const0) return b; if (sel == const1) return a; int t1 = AND(sel, a); int t2 = AND(NOT(sel), b); return OR(t1, t2); } static int ceil_log2_int(int x) { if (x <= 1) return 0; int b = 0; int p = 1; while (p < x) { p <<= 1; b++; } return b; } // Compare two B-bit unsigned numbers (bits are little-endian: bits[0] is LSB) // Returns node id = 1 iff a < b int LT_bits(const vector<int>& a, const vector<int>& b, int B) { int less = const0; int equal = const1; for (int i = B - 1; i >= 0; i--) { int ai = a[i]; int bi = b[i]; int ai_lt_bi = AND(NOT(ai), bi); less = OR(less, AND(equal, ai_lt_bi)); int diff = XOR(ai, bi); equal = AND(equal, NOT(diff)); } return less; } int buildMachine(const vector<vector<int>>& adj, bool isAlice) { // Special small case n==1: just output membership of the only vertex. if (n == 1) { int out = COPY(0); int sink = COPY(out); return sink; } const int B = ceil_log2_int(n); // bits for vertex id const int T = B; // iterations const int Lstage = B + 2; // per iteration: B index bits, 1 valid bit, 1 membership bit const int R = T * Lstage; // scheduled rounds // transcript bits z[0..2k-1] are sources n..n+2k-1 vector<int> z(2 * k); for (int i = 0; i < 2 * k; i++) z[i] = n + i; // Stage detection vector<int> notZ(2 * k); for (int i = 0; i < 2 * k; i++) notZ[i] = NOT(z[i]); vector<int> suffixZero(2 * k + 1); suffixZero[2 * k] = const1; for (int i = 2 * k - 1; i >= 0; i--) { suffixZero[i] = AND(notZ[i], suffixZero[i + 1]); } vector<int> isStage(R, const0); isStage[0] = suffixZero[0]; for (int i = 1; i < R; i++) { // marker at position 2*i must be 1, and everything after must be 0 isStage[i] = AND(z[2 '' i], suffixZero[2 '' i + 1]); } // isPos[p] = OR of isStage at all iterations with same position p vector<int> isPos(Lstage, const0); for (int p = 0; p < Lstage; p++) { int r = const0; for (int t = 0; t < T; t++) { r = OR(r, isStage[t * Lstage + p]); } isPos[p] = r; } // isIter[t] = OR of all stages of iteration t vector<int> isIter(T, const0); for (int t = 0; t < T; t++) { int r = const0; for (int p = 0; p < Lstage; p++) { r = OR(r, isStage[t * Lstage + p]); } isIter[t] = r; } // Decode x_t (Alice) and y_t (Bob) bits from transcript vector<vector<int>> xBits(T, vector<int>(B, const0)); vector<vector<int>> yBits(T, vector<int>(B, const0)); vector<int> validA(T, const0), validB(T, const0); for (int t = 0; t < T; t++) { int base = t * Lstage; for (int b = 0; b < B; b++) { xBits[t][b] = z[2 * (base + b)]; yBits[t][b] = z[2 * (base + b) + 1]; } int vStage = base + B; validA[t] = z[2 * vStage]; validB[t] = z[2 * vStage + 1]; } // Precompute negations of bits for faster equality checks vector<vector<int>> nxBits(T, vector<int>(B, const0)); vector<vector<int>> nyBits(T, vector<int>(B, const0)); for (int t = 0; t < T; t++) { for (int b = 0; b < B; b++) { nxBits[t][b] = NOT(xBits[t][b]); nyBits[t][b] = NOT(yBits[t][b]); } } // eqX[t][v] = (x_t == v) & validA[t] // eqY[t][v] = (y_t == v) & validB[t] vector<vector<int>> eqX(T, vector<int>(n, const0)); vector<vector<int>> eqY(T, vector<int>(n, const0)); for (int t = 0; t < T; t++) { for (int v = 0; v < n; v++) { int eq = const1; for (int b = 0; b < B; b++) { eq = AND(eq, ((v >> b) & 1) ? xBits[t][b] : nxBits[t][b]); } eqX[t][v] = AND(eq, validA[t]); } for (int v = 0; v < n; v++) { int eq = const1; for (int b = 0; b < B; b++) { eq = AND(eq, ((v >> b) & 1) ? yBits[t][b] : nyBits[t][b]); } eqY[t][v] = AND(eq, validB[t]); } } // alive sets S_t vector<vector<int>> alive(T + 1, vector<int>(n, const1)); for (int t = 0; t < T; t++) { int bothValid = AND(validA[t], validB[t]); vector<int> neighX(n, const0), neighY(n, const0); for (int v = 0; v < n; v++) { int r1 = const0; for (int u : adj[v]) r1 = OR(r1, eqX[t][u]); neighX[v] = r1; int r2 = const0; for (int u : adj[v]) r2 = OR(r2, eqY[t][u]); neighY[v] = r2; } for (int v = 0; v < n; v++) { int keep = alive[t][v]; keep = AND(keep, neighX[v]); keep = AND(keep, NOT(neighY[v])); keep = AND(keep, NOT(eqX[t][v])); keep = AND(keep, NOT(eqY[t][v])); keep = AND(keep, bothValid); alive[t + 1][v] = keep; } } // aliveCur[v] = alive[t][v] for current iteration t vector<int> aliveCur(n, const0); for (int v = 0; v < n; v++) { int r = const0; for (int t = 0; t < T; t++) { r = OR(r, AND(isIter[t], alive[t][v])); } aliveCur[v] = r; } // degrees in current S (aliveCur) vector<vector<int>> degBits(n, vector<int>(B, const0)); for (int v = 0; v < n; v++) { vector<int> deg(B, const0); for (int u : adj[v]) { int carry = aliveCur[u]; for (int b = 0; b < B; b++) { int old = deg[b]; int sum = XOR(old, carry); int newCarry = AND(old, carry); deg[b] = sum; carry = newCarry; } } for (int b = 0; b < B; b++) degBits[v][b] = deg[b]; } // candidate[v] = ownSet[v] & aliveCur[v] vector<int> candidate(n, const0); for (int v = 0; v < n; v++) { int own = v; // source id candidate[v] = AND(own, aliveCur[v]); } // validCur = OR_v candidate[v] int validCur = const0; for (int v = 0; v < n; v++) validCur = OR(validCur, candidate[v]); // Select best vertex index bits vector<int> bestIdx(B, const0); vector<int> bestDeg(B, const0); int bestAny = const0; // whether we already picked a candidate for (int v = 0; v < n; v++) { int cand = candidate[v]; int take; if (isAlice) { // take if cand and (no best yet or deg[v] < bestDeg) int better = LT_bits(degBits[v], bestDeg, B); take = AND(cand, OR(NOT(bestAny), better)); } else { // take if cand and (no best yet or deg[v] >= bestDeg) int worse = LT_bits(degBits[v], bestDeg, B); // deg[v] < bestDeg int ge = NOT(worse); take = AND(cand, OR(NOT(bestAny), ge)); } bestAny = OR(bestAny, cand); int notTake = NOT(take); for (int b = 0; b < B; b++) { int vb = ((v >> b) & 1) ? const1 : const0; // bestIdx[b] = take ? vb : bestIdx[b] if (vb == const1) { bestIdx[b] = OR(bestIdx[b], take); } else { bestIdx[b] = AND(bestIdx[b], notTake); } // bestDeg[b] = take ? degBits[v][b] : bestDeg[b] bestDeg[b] = OR(AND(take, degBits[v][b]), AND(notTake, bestDeg[b])); } } // Membership check per iteration t vector<int> memPerIter(T, const0); for (int t = 0; t < T; t++) { const vector<int>& oppEq = isAlice ? eqY[t] : eqX[t]; int r = const0; for (int v = 0; v < n; v++) { int own = v; r = OR(r, AND(own, oppEq[v])); } memPerIter[t] = r; } int memBit = const0; for (int t = 0; t < T; t++) { memBit = OR(memBit, AND(isIter[t], memPerIter[t])); } // Output for scheduled stages int outScheduled = const0; for (int p = 0; p < B; p++) { outScheduled = OR(outScheduled, AND(isPos[p], bestIdx[p])); } outScheduled = OR(outScheduled, AND(isPos[B], validCur)); outScheduled = OR(outScheduled, AND(isPos[B + 1], memBit)); // foundOverall = OR of all membership outputs (both machines) from transcript int foundOverall = const0; for (int t = 0; t < T; t++) { int stage = t * Lstage + (B + 1); int a_mem = z[2 * stage]; int b_mem = z[2 * stage + 1]; foundOverall = OR(foundOverall, OR(a_mem, b_mem)); } // earlyStage = OR_{i < R} isStage[i] int earlyStage = const0; for (int i = 0; i < R; i++) earlyStage = OR(earlyStage, isStage[i]); int out = MUX(earlyStage, outScheduled, foundOverall); // Ensure sink is last node int sink = COPY(out); return sink; } }; static const char* FSTR[16] = { "0000","1000","0100","1100", "0010","1010","0110","1110", "0001","1001","0101","1101", "0011","1011","0111","1111" }; static void printMachine(const CircuitBuilder& cb) { FastOutput out; int totalNodes = cb.L + (int)cb.nodes.size(); out.putInt(totalNodes); out.putChar('\n'); for (const auto& nd : cb.nodes) { out.putInt(nd.x); out.putChar(' '); out.putInt(nd.y); out.putChar(' '); out.putStr(FSTR[nd.f]); out.putChar('\n'); } out.flush(); cout.flush(); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, k; cin >> n >> m >> k; vector<vector<int>> adj(n); adj.reserve(n); for (int i = 0; i < m; i++) { int a, b; cin >> a >> b; --a; --b; adj[a].push_back(b); adj[b].push_back(a); } // Alice { CircuitBuilder cb(n, k, 1500000); cb.buildMachine(adj, true); printMachine(cb); } // Bob { CircuitBuilder cb(n, k, 1500000); cb.buildMachine(adj, false); printMachine(cb); } return 0; } </syntaxhighlight> ์ํ๋ฉด(ํน์ ๋ WA๊ฐ ๋จ๋ฉด) ๋ค ์ ์ถ ๋ก๊ทธ์์ ์ฒซ ์ค์ <code>t</code> ๊ฐ์ด ์ผ๋ง์๋์ง(ํนํ 1,500,000 ์ด๊ณผ์๋์ง) ํ์ธํด์ฃผ๋ฉด, ๊ทธ ๊ฐ ๊ธฐ์ค์ผ๋ก ๋ ๊น๋(์: valid-stage ์ ๊ฑฐ/์ถ๊ฐ ํด๋ฉ) ๋ฒ์ ๋ ๋ฐ๋ก ๋ง์ถฐ์ค๊ฒ์.
Summary:
Please note that all contributions to freem are considered to be released under the Creative Commons Attribution-ShareAlike 4.0 (see
Freem:Copyrights
for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.
Do not submit copyrighted work without permission!
Cancel
Editing help
(opens in new window)