#include #include #include #include #include #include #include #include #include #include #include typedef long long llong; const int MAXN = 1000000 + 10; const int INTINF = 1e9; const llong INF = 1e18; const int MAXLOG = 17; int n; int a[MAXN]; int b[MAXN]; int perm[MAXN]; std::mt19937 rng(std::chrono::steady_clock::now().time_since_epoch().count()); struct Operation { int type, pos, val; friend bool operator < (const Operation &a, const Operation &b) { return a.pos < b.pos || (a.pos == b.pos && a.val < b.val); } }; struct Triple { int resAND, resOR, resXOR; friend bool operator == (const Triple &a, const Triple &b) { return a.resAND == b.resAND && a.resOR == b.resOR && a.resXOR == b.resXOR; } }; Triple getTriple(int cntOnes, int cntZeros) { return {(cntZeros == 0), (cntOnes == 0), (cntOnes & 1)}; } void solve() { if (n <= 20) { std::cout << n << '\n'; for (int i = 1 ; i <= n ; ++i) { std::cout << 1 << ' ' << i << ' ' << 0 << '\n'; } return; } std::iota(perm + 1, perm + 1 + n, 1); std::shuffle(perm + 1, perm + 1 + n, rng); std::vector v; v.push_back({1, perm[1], 0}); v.push_back({2, perm[2], (1 << 20) - 1}); a[perm[1]] = b[perm[1]] = 0; a[perm[2]] = b[perm[2]] = (1 << 20) - 1; for (int bit = 19 ; bit >= 0 ; --bit) { int cntA[2] = {0, 0}; int cntB[2] = {0, 0}; for (int i = 1 ; i <= n ; ++i) { cntA[((a[i] & (1 << bit)) > 0)]++; cntB[((b[i] & (1 << bit)) > 0)]++; } if (getTriple(cntA[1], cntA[0]) == getTriple(cntB[1], cntB[0])) { continue; } bool found = false; for (int i = 1 ; i <= n ; ++i) { cntA[((a[perm[i]] & (1 << bit)) > 0)]--; cntB[((b[perm[i]] & (1 << bit)) > 0)]--; // cntA[((a[i] & (1 << bit)) > 0) ^ 1]++; // cntB[((b[i] & (1 << bit)) > 0) ^ 1]++; // if (getTriple(cntA[1], cntA[0]) == getTriple(cntB[1], cntB[0])) // { // v.push_back({3, i, (1 << bit)}); // a[i] ^= (1 << bit); // b[i] ^= (1 << bit); // found = true; // break; // } // cntA[((a[i] & (1 << bit)) > 0) ^ 1]--; // cntB[((b[i] & (1 << bit)) > 0) ^ 1]--; cntA[0]++; cntB[0]++; if (getTriple(cntA[1], cntA[0]) == getTriple(cntB[1], cntB[0])) { v.push_back({1, perm[i], (1 << 20) - 1 - (1 << bit)}); a[perm[i]] &= (1 << 20) - 1 - (1 << bit); b[perm[i]] &= (1 << 20) - 1 - (1 << bit); found = true; break; } cntA[0]--; cntB[0]--; cntA[1]++; cntB[1]++; if (getTriple(cntA[1], cntA[0]) == getTriple(cntB[1], cntB[0])) { v.push_back({2, perm[i], (1 << bit)}); a[perm[i]] |= (1 << bit); b[perm[i]] |= (1 << bit); found = true; break; } cntA[1]--; cntB[1]--; cntA[((a[perm[i]] & (1 << bit)) > 0)]++; cntB[((b[perm[i]] & (1 << bit)) > 0)]++; } assert(found); } // std::cout << "operations: " << v.size() << '\n'; std::sort(v.begin(), v.end()); std::vector newV; for (const Operation &p : v) { if (newV.empty() || newV.back().pos != p.pos || newV.back().type != p.type) { newV.push_back(p); } else { if (newV.back().type == 1 && p.type == 1) { newV.back().val &= p.val; } else if (newV.back().type == 2 && p.type == 2) { newV.back().val |= p.val; } else { assert(false); } } } v = newV; std::cout << v.size() << '\n'; for (const auto &[type, idx, val] : v) { std::cout << type << ' ' << idx << ' ' << val << '\n'; } // int aOR = 0; // int aXOR = 0; // int aAND = (1 << 20) - 1; // for (int i = 1 ; i <= n ; ++i) // { // aOR |= a[i]; // aXOR ^= a[i]; // aAND &= a[i]; // } // int bOR = 0; // int bXOR = 0; // int bAND = (1 << 20) - 1; // for (int i = 1 ; i <= n ; ++i) // { // bOR |= b[i]; // bXOR ^= b[i]; // bAND &= b[i]; // } // std::cout << aOR << ' ' << aXOR << ' ' << aAND << '\n'; // std::cout << bOR << ' ' << bXOR << ' ' << bAND << '\n'; } void input() { std::cin >> n; for (int i = 1 ; i <= n ; ++i) std::cin >> a[i]; for (int i = 1 ; i <= n ; ++i) std::cin >> b[i]; } void fastIOI() { freopen("homework.in", "r", stdin); freopen("homework.out", "w", stdout); std::ios_base :: sync_with_stdio(0); std::cout.tie(nullptr); std::cin.tie(nullptr); } int main() { fastIOI(); input(); solve(); return 0; }