Problem:
問題 I : ビット演算
いよいよ G○○gle Code Jam の世界大会が始まろうとしている．
前では P○tr, t○mek, SnapDrag○n をはじめとする，
G○○gle の誇る最強のコーダー達が睨みを利かせている．
妙な動きを見せれば，命はないだろう．
目をつむり，コンテスト開始をじっと待つ．
…妙だ，コンテストが始まらない．
目を開けてみると…なんということだ．部屋の全ての人間が，倒れている．
いや違う，全てではない．一人の男，wata を除いてだ．
wata
「やっと話せるぞ． 久しぶりだな，(iwi)」
(iwi)
「…お前は何者だ？ 俺の知る wata は幼なじみ系美少女のはずが…」
wata
「まだそんな妄想に取り憑かれているのか!! 思い出せ!! 受け止めろ!! 彼はもうこの世界には居ないんだ!!」
はっ…!! 僕は全てを思い出していた．
僕は世界で最初にプログラミングコンテストで人を殺めたのだ．
そして，僕が殺したのは他でもなく，最も仲の良かった友人の一人，kita_masa であった．
kita_masa は自らをビット演算の達人と言い，
あらゆる関数はビット演算で記述できると言う，少し変わった奴だった．
そういえば今，ビット演算を用いて作成したい関数があるが，
kita_masa にそれをお願いすることはできない．
そこで，kita_masa の代わりになるプログラムを作成することにした．
問題
N
個の整数の組
(
x
i
,
y
i
)
が与えられる．
全ての組に対して
y
i
=
f
(
x
i
)
なる関数
f
を制約の下で作ることを考える．
関数
f
は，C 言語のソースコードとして以下のように表現できるものとする:
uint32_t f(uint32_t x) {
  return 式;
}
ここで，uint32_t は 32 ビット符号無し整数を表す．
また，式は以下の BNF で表現できるものとする:
<expr> ::= "x"
         | <num>
         | "(~" <expr> ")"
         | "(" <expr> <op2> <expr> ")"
<op2> ::= "&" | "|" | "^" | "+" | "-" | "*"
<num> は 32 ビット符号無し整数で表現できる非負の整数を
10 進数で自然に (leading-zero 等を持たず) 表現したものとする．
このような関数の式を出力するプログラムを作成せよ．
入力
入力の最初の行は 1 つの整数
N
を含む．
続く
N
行の
i
行目は 2 つの整数
x
i
,
y
i
を含む．
出力
条件を満たす式を出力せよ．
制約
1 ≤
N
≤ 8
0 ≤
x
i
,
y
i
< 256
式は必ず，上記の BNF に従う書式で出力せよ．例え C 言語の表現として妥当であったとしても，空白や改行の挿入や括弧の削除などはしてはならない．
出力は 100000 文字を越えてはならない．
条件を満たす関数
f
が常に存在するような入力が与えられる．
部分点
この問題の判定には，20 点分のテストケースのグループが設定されている．
このグループに含まれるテストケースの入力は以下を満たす．
'+', '-', '*' を用いないような正しい出力が存在する
入出力例
入力例1:
8
1 1
2 2
3 3
4 0
5 1
6 2
7 3
8 0
入力例 1 に対する出力の例:
(x&3)
入力例2:
8
1 0
2 0
3 2
4 0
5 4
6 4
7 6
8 0
入力例 2 に対する出力の例:
(x&(x-1))
良く知られる最右の 1 ビットをオフにする操作である．

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)

using namespace std;

typedef unsigned uint;
string num(uint n){
    stringstream ss;
    ss << n;
    return ss.str();
}
string negative(string expr){
    return "(~" + expr + ")";
}
string operate(string expr1, string expr2, char op){
    return "(" + expr1 + op + expr2 +")";
}
int main(){
    int N;
    while(cin >> N){
        vector<uint> x(N);
        vector<uint> y(N);
        REP(i, N) cin >> x[i] >> y[i];
        string ans = "0";
        for(int t = 0, s = 1; t < 8; t++, s<<=1){
            // add
            vector<uint> b(N); // lowest bit
            REP(i, N) b[i] = (y[i] >> t) & 1;
      //REP(i,N) cout << b[i] << " ";
      //cout << endl;
            if(b == vector<uint>(N, 0)) continue;

            map<vector<uint>, string> e_dict;
            for(uint dx = 0; dx < 256; dx++){
                vector<uint> fb(N);

                //constant
                REP(i, N) fb[i] = dx >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = num(dx);
      //REP(i,N) cout << fb[i] << " ";
     // cout << num(dx) << " " << e_dict[fb] << endl;

                if(dx == 0){
                    REP(i, N) fb[i] = x[i] >> t & 1;
                    if(!e_dict.count(fb)) e_dict[fb] = "x";
                    continue;
                }

                // add
                REP(i, N) fb[i] = (x[i] + dx) >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = operate("x", num(dx), '+');

                // sub
                REP(i, N) fb[i] = (x[i] - dx) >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = operate("x", num(dx), '-');

                // mul
                REP(i, N) fb[i] = (x[i] * dx) >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = operate("x", num(dx), '*');
            }
            bool update = true;
            while(update && !e_dict.count(b)){
                update = false;
                map<vector<uint>, string> new_dict;
                for(auto& p : e_dict)
                for(auto& q : e_dict){
                    vector<uint> fb(N);
                    REP(i, N) fb[i] = (p.first[i] & q.first[i]);
                    if(!new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = operate(p.second, q.second, '&');
                    }
                    REP(i, N) fb[i] = (p.first[i] | q.first[i]);
                    if(!new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = operate(p.second, q.second, '|');
                    }
                    REP(i, N) fb[i] = (p.first[i] ^ q.first[i]);
                    if(!new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = operate(p.second, q.second, '^');
                    }
                }
                for(auto& p : e_dict){
                    vector<uint> fb(N);
                    REP(i, N) fb[i] = ~p.first[i];
                    if(new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = negative(p.second);
                    }
                }
                if(update) e_dict.swap(new_dict);
            }
            assert(e_dict.count(b));
            ans = operate(ans, operate(e_dict[b], num(s), '&'), '|');
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3532
final_rank: 2

code_snippet: #include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < int(n); ++ (i))
using namespace std;
template <typename X, typename T> auto vectors(X x, T a) { return vector<T>(x, a); }
template <typename X, typename Y, typename Z, typename... Zs> auto vectors(X x, Y y, Z z, Zs... zs) { auto cont = vectors(y, z, zs...); return vector<decltype(cont)>(x, cont); }

void check(int n, vector<uint32_t> const & x, vector<uint32_t> const & y) {
    auto distinguishable = vectors(n, n, bool());
    REP (k, 8) {
        REP (j, n) REP (i, j) if (i != j) {
            if ((x[i] & (1 << k)) != (x[j] & (1 << k))) {
                distinguishable[i][j] = true;
            }
            if ((y[i] & (1 << k)) != (y[j] & (1 << k))) {
                assert (distinguishable[i][j]);
            }
        }
    }
}

uint8_t kth_column(vector<uint32_t> const & x, int k) {
    int n = x.size();
    assert (n <= 8);
    uint8_t acc = 0;
    REP (i, n) {
        if (x[i] & (1 << k)) {
            acc |= 1 << i;
        }
    }
    return acc;
}

int main() {
    // input
    int n; cin >> n;
    vector<uint32_t> x(n), y(n);
    REP (i, n) cin >> x[i] >> y[i];
    // solve
    check(n, x, y);
    string result = "0";
    vector<string> memo(1 << n);
    memo[0] = "0";
    memo[(1 << n) - 1] = "1";
    REP (k, 8) {
        // prepare a queue
        queue<uint8_t> que;
        auto push = [&](uint8_t a, string const & s) {
            if (memo[a].empty()) {
                que.push(a);
                memo[a] = s;
            }
        };
        { // add a new primitive
            ostringstream oss;
            oss << "(x&" << (1 << k) << ")";
            push(kth_column(x, k), oss.str());
        }
        // breath first search
        while (not que.empty()) {
            uint8_t a = que.front(); que.pop();
            string s = memo[a];
            {
                ostringstream oss;
                oss << "((~" << s << ")&" << (1 << k) << ")";
                push((~ a) & ((1 << n) - 1), oss.str());
            }
            REP (b, 1 << n) if (not memo[b].empty()) {
                string t = memo[b];
                push(a & b, "(" + s + "&" + t + ")");
                push(a | b, "(" + s + "|" + t + ")");
                push(a ^ b, "(" + s + "^" + t + ")");
            }
        }
        // add to the result
        assert (not memo[kth_column(y, k)].empty());
        result = "(" + result + "|" + memo[kth_column(y, k)] + ")";
        // lshift old items
        REP (a, 1 << n) if (not memo[a].empty()) {
            memo[a] = "(" + memo[a] + "*2)";
        }
    }
    // output
    cout << result << endl;
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3288
final_rank: 4

code_snippet: #include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)

using namespace std;
typedef long long ll;

const int    INF = 1000000000;
const int    MOD = 1000000007;
const double EPS = 1e-8;
typedef unsigned uint;
string num(uint n){
    stringstream ss;
    ss << n;
    return ss.str();
}
string negative(string expr){
    return "(~" + expr + ")";
}
string operate(string expr1, string expr2, char op){
    return "(" + expr1 + op + expr2 +")";
}
int main(){
    int N;
    while(cin >> N){
        vector<uint> x(N);
        vector<uint> y(N);
        REP(i, N) cin >> x[i] >> y[i];
        string ans = "0";
        for(int t = 0, s = 1; t < 8; t++, s<<=1){
            // add
            vector<uint> b(N); // lowest bit
            REP(i, N) b[i] = (y[i] >> t) & 1;

            if(b == vector<uint>(N, 0)) continue;

            map<vector<uint>, string> e_dict;
            for(uint dx = 0; dx < 256; dx++){
                vector<uint> fb(N);

                //constant
                REP(i, N) fb[i] = dx >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = num(dx);

                if(dx == 0){
                    REP(i, N) fb[i] = x[i] >> t & 1;
                    if(!e_dict.count(fb)) e_dict[fb] = "x";
                    continue;
                }

                // add
                REP(i, N) fb[i] = (x[i] + dx) >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = operate("x", num(dx), '+');

                /*
                // sub
                REP(i, N) fb[i] = (x[i] - dx) >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = operate("x", num(dx), '-');

                // mul
                REP(i, N) fb[i] = (x[i] * dx) >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = operate("x", num(dx), '*');
                */
            }
            bool update = true;
            while(update && !e_dict.count(b)){
                update = false;
                map<vector<uint>, string> new_dict;
                for(auto& p : e_dict)
                for(auto& q : e_dict){
                    vector<uint> fb(N);
                    REP(i, N) fb[i] = (p.first[i] & q.first[i]);
                    if(!new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = operate(p.second, q.second, '&');
                    }
                    REP(i, N) fb[i] = (p.first[i] | q.first[i]);
                    if(!new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = operate(p.second, q.second, '|');
                    }
                    REP(i, N) fb[i] = (p.first[i] ^ q.first[i]);
                    if(!new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = operate(p.second, q.second, '^');
                    }
                }
                for(auto& p : e_dict){
                    vector<uint> fb(N);
                    REP(i, N) fb[i] = ~p.first[i];
                    if(new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = negative(p.second);
                    }
                }
                if(update) e_dict.swap(new_dict);
            }
            assert(e_dict.count(b));
            ans = operate(ans, operate(e_dict[b], num(s), '&'), '|');
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1372
final_rank: 3

code_snippet: #include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#define REP(i,n) for(int i=0; i<(int)(n); ++i)

using namespace std;
typedef long long ll;

const int    INF = 1000000000;
const int    MOD = 1000000007;
const double EPS = 1e-8;
typedef unsigned uint;
string num(uint n){
    stringstream ss;
    ss << n;
    return ss.str();
}
string negative(string expr){
    return "(~" + expr + ")";
}
string operate(string expr1, string expr2, char op){
    return "(" + expr1 + op + expr2 +")";
}
int main(){
    int N;
    while(cin >> N){
        vector<uint> x(N);
        vector<uint> y(N);
        REP(i, N) cin >> x[i] >> y[i];
        string ans = "0";
        for(int t = 0, s = 1; t < 8; t++, s<<=1){
            // add
            vector<uint> b(N); // lowest bit
            REP(i, N) b[i] = (y[i] >> t) & 1;

            if(b == vector<uint>(N, 0)) continue;

            map<vector<uint>, string> e_dict;
            for(uint dx = 0; dx < 256; dx++){
                vector<uint> fb(N);

                //constant
                REP(i, N) fb[i] = dx >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = num(dx);

                if(dx == 0){
                    REP(i, N) fb[i] = x[i] >> t & 1;
                    if(!e_dict.count(fb)) e_dict[fb] = "x";
                    continue;
                }

                // add
                REP(i, N) fb[i] = (x[i] + dx) >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = operate("x", num(dx), '+');

                // sub
                REP(i, N) fb[i] = (x[i] - dx) >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = operate("x", num(dx), '-');

                // mul
                REP(i, N) fb[i] = (x[i] * dx) >> t & 1;
                if(!e_dict.count(fb)) e_dict[fb] = operate("x", num(dx), '*');
            }
            bool update = true;
            while(update && !e_dict.count(b)){
                update = false;
                map<vector<uint>, string> new_dict;
                for(auto& p : e_dict)
                for(auto& q : e_dict){
                    vector<uint> fb(N);
                    REP(i, N) fb[i] = (p.first[i] & q.first[i]);
                    if(!new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = operate(p.second, q.second, '&');
                    }
                    REP(i, N) fb[i] = (p.first[i] | q.first[i]);
                    if(!new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = operate(p.second, q.second, '|');
                    }
                    REP(i, N) fb[i] = (p.first[i] ^ q.first[i]);
                    if(!new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = operate(p.second, q.second, '^');
                    }
                }
                for(auto& p : e_dict){
                    vector<uint> fb(N);
                    REP(i, N) fb[i] = ~p.first[i];
                    if(new_dict.count(fb)){
                        update = true;
                        new_dict[fb] = negative(p.second);
                    }
                }
                if(update) e_dict.swap(new_dict);
            }
            assert(e_dict.count(b));
            ans = operate(ans, operate(e_dict[b], num(s), '&'), '|');
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1344
final_rank: 1