int main() {
         int n = 10;
         int a[n];

         int bit_n[1 << n]; // n-bit numbers
         bit_n[0] = 0;
         for (int i = 1; i < (1 << n); i++)
           bit_n[i] = bit_n[i >> 1] + (i & 1);

         int upper[1 << n]; // n-bit numbers
         upper[0] = -1;
         for (int i = 1; i < (1 << n); i++)
           upper[i] = upper[i >> 1] + 1;

         int sum[1 << n]; // n-bit numbers
         sum[0] = 0;
         for (int i = 1; i < (1 << n); i++)
           sum[i] = sum[i ^ (1 << upper[i])] + a[upper[i]];

         /** Time(n) = 2^n, n <= 40 */
         /** 
           if A is proper subset of B then A < B
         */

         long long adjacentSet[vertexN];
         // adjacentSet[v] -- множество смежных с v вершин
         // vertexN <= 64

         $\forall$ setOfVertices
         isIndependentSet[setOfVertices]
         bool isIndependentSet[1 << vertexN];
         isIndependentSet[0] = 1;
         for (int p = 1; p < (1 << vertexN); p++)
           isIndependentSet[p] = 
             isIndependentSet[p ^ upper[p]] &&
             (adjacentSet[upper[p]] & p) == 0;
         /** Time = O(2^vertexN) */
         
         /**
           объединение = A | B
           пересечение = A & B
           разность    = A & ~B
         */

         /** Гамильтонов путь -> Гамильтонов цикл -> Коммивояжёр */
         /** Гамильтонов путь */
         // O(n!)
         // O(2^n * n^2) --> O(2^n * n)
         // isPath[setOfVertices, lastVertex] = 0 or 1
         int n = vertexN;
         bool isPath[1 << n][n];
         for (int v = 0; v < n; v++)
           isPath[1 << v][v] = 1;
         for (int p = 0; p < (1 << n); p++)
           for (int last = 0; last < n; last++)
             if (isPath[p][last])
               for (int next = 0; next < n; next++)
                 if (isEdge[last][next]) // матрица смежности
                   isPath[p | (1 << next)][next] = 1;
         bool result = 0;
         for (int last = 0; last < n; last++)
           result |= isPath[(1 << n) - 1][last];

         /*** optimize #1 */
         int n = vertexN;
         int possibleEnds[1 << n];
         for (int v = 0; v < n; v++)
           possibleEnds[1 << v] = 1 << v;
         for (int p = 0; p < (1 << n); p++)
           for (int last = 0; last < n; last++)
             if ((possibleEnds[p] >> last) & 1)
               for (int next = 0; next < n; next++)
                 if (isEdge[last][next]) // матрица смежности
                   isPath[p | (1 << next)] |= 1 << next;

         /*** optimize #2 */
         int n = vertexN;
         int possibleEnds[1 << n];
         for (int v = 0; v < n; v++)
           possibleEnds[1 << v] = 1 << v;
         for (int p = 0; p < (1 << n); p++)
           for (int next = 0; next < n; next++)
             if (possibleEnds[p] & adjacentSet[next])
               isPath[p | (1 << next)] |= 1 << next;
       }