#include <vector>
#include <string>
#include <iostream>
#include <iomanip>

using namespace std;

class Gray
{
public:
    Gray(int N):N(N),a(N+1,false),last_(-1){}
    ~Gray() = default;
    Gray(const Gray&) = default;
    Gray(Gray&&)      = default;
    Gray& operator=(const Gray&) = default;
    Gray& operator=(Gray&&)      = default;

    size_t size() const { return N; }
    void reset(size_t newN = 0)
    {
        if (newN) N = newN;
        vector<bool> b(N+1,false);
        std::swap(a,b);
        last_ = -1;
    }

    bool operator[](size_t idx) const { return a[idx]; }

    int  last() const { return last_; }

    bool next()
    {
        size_t j;
        if (!a[N]) j = 0; else {
            for(j = 0; j < N; ++j) if (a[j]) break;
            ++j;
        }
        if (j == N) return false;
        a[N] = !a[N];
        a[j] = !a[j];
        last_ = j;
        return true;
    }
private:
    vector<bool> a;
    size_t N;
    int last_;
};



int main(int argc, const char * argv[])
{
    int m[] = { 2, 3, 5, 7 };

    Gray g(sizeof(m)/sizeof(m[0]));
    do {
        if (g.last() >= 0)
        {
            int p = 1;
            for(size_t i = 0; i < g.size(); ++i) if (g[i]) p *= m[i];
            cout << setw(6) << p << " = ";
            for(size_t i = 0, first = 1; i < g.size(); ++i)
                if (g[i]) {
                    if (!first)
                    {
                        cout << " * ";
                    }
                    else
                    {
                        first = 0;
                    }
                    cout << m[i];
                }
            cout << "\n";
        }
    } while(g.next());

    // Только произведения - если нет нулевого элемента.

    g.reset();

    int p = 1;
    do {
        if (g.last() >= 0)
        {
            if (g[g.last()]) p *= m[g.last()]; else p /= m[g.last()];
            cout << setw(6) << p <<"\n";
        }
    } while(g.next());

}
