// 累積nandをとっていった時、全てが1でない場合も0になり得るのか。。。 // それを全く考慮していなかった。。。 ショック。 #include // clang-format off using namespace std;constexpr int INF=1001001001;constexpr long long INFll=1001001001001001001;namespace viewer{template string f(T i){string s=(i==INF||i==INFll?"inf":to_string(i));s=string(max(0,3-int(s.size())),' ')+s;return s;} templateauto v(T&x,string end)->decltype(cerr<void v(const pair&p,string end="\n"){cerr<<"(";v(p.first,", ");v(p.second,")"+end);}templatevoid v(const tuple&t,string end="\n"){auto[a,b]=t;cerr<<"(";v(a,", ");v(b,")"+end);}templatevoid v(const tuple&t,string end="\n"){auto[a,b,c]=t;cerr<<"(";v(a,", ");v(b,", ");v(c,")"+end);}templatevoid v(const tuple&t,string end="\n"){auto[a,b,c,d]=t;cerr<<"(";v(a,", ");v(b,", ");v(c,", ");v(d,")"+end);} templatevoid v(const vector&vx,string);templateauto ve(int,const vector&vx)->decltype(cerr<auto ve(bool,const vector &vx){cerr << "{\n";for(const T&x:vx)cerr<<" ",v(x,",");cerr<<"}\n";}templatevoid v(const vector&vx, string){ve(0,vx);}templatevoid v(const deque&s,string e){vectorz(s.begin(),s.end());v(z,e);} templatevoid v(const set&s,string e){vectorz(s.begin(),s.end());v(z,e);}templatevoid v(const multiset&s,string e){vectorz(s.begin(),s.end());v(z,e);}templatevoid v(const unordered_set&s,string e){vectorz(s.begin(),s.end());v(z,e);}templatevoid v(const priority_queue&p,string e){priority_queueq=p;vectorz;while(!q.empty()){z.push_back(q.top());q.pop();}v(z,e);} templatevoid v(const map&m,string e){cerr<<"{"<<(m.empty()?"":"\n");for(const auto&kv:m){cerr<<" [";v(kv.first,"");cerr<<"] : ";v(kv.second,"");cerr<<"\n";}cerr<<"}"+e;}templatevoid _view(int n,string s,T&var){cerr<<"\033[1;32m"<void grid(T _){}void grid(const vector>&vvb){cerr<<"\n";for(const vector&vb:vvb){for(const bool&b:vb)cerr<<(b?".":"#");cerr<<"\n";}} void _debug(int,string){}templatevoid _debug(int n,string S,H h,T... t){int i=0,cnt=0;for(;iap;mint re=a;for(long long r=1;r> N; int M; cin >> M; string X; cin >> X; vector> ans; vector As(N * M + 1); for (int i = 0; i < N; i++) { cin >> As[i]; for (int j = 1; j < M; j++) { As[i + j * N] = As[i + (j - 1) * N].substr(1) + "0"; ans.emplace_back(1, i + j * N, i + (j - 1) * N); } } As[N * M] = string(M, '0'); // debug(As); vector> candis; for (int i = 0; i < N * M + 1; i++) { candis.emplace_back(As[i], i + 1); } for (int keta = 0; keta < M; keta++) { if (X[keta] == '0') { vector> ncandis; for (int i = 0; i < int(candis.size()); i++) { if (candis[i].first[keta] == '1') { ncandis.emplace_back(candis[i]); } } swap(ncandis, candis); } } for (int keta = 0; keta < M; keta++) { if (X[keta] == '1') { bool ok = false; for (int i = 0; i < int(candis.size()); i++) { if (candis[i].first[keta] == '0') { ok = true; break; } } if (!ok) { cout << -1 << endl; return 0; } } } debug(candis); if (candis.size() <= 1) { cout << -1 << endl; return 0; } assert(int(ans.size()) + int(candis.size()) - 1 <= 1000); cout << int(ans.size()) + int(candis.size()) - 1 << endl; for (int i = 0; i < (int)ans.size(); i++) { auto [x, y, z] = ans[i]; cout << x << " " << y + 1 << " " << z + 1 << "\n"; } for (int i = 0; i < int(candis.size()) - 2; i++) { cout << 2 << " " << candis[i + 1].second << " " << candis[i].second << " " << candis[i + 1].second << endl; candis[i + 1].first = f(candis[i].first, candis[i + 1].first); } cout << 2 << " " << 0 << " " << candis[int(candis.size()) - 2].second << " " << candis[int(candis.size()) - 1].second << endl; debug(X); debug(f(candis[int(candis.size()) - 2].first, candis[int(candis.size()) - 1].first)); assert(X == f(candis[int(candis.size()) - 2].first, candis[int(candis.size()) - 1].first)); return 0; } // (10100011, 3), (11101110, 6), (10111110, 19), (10110111, 29), (11111010, 51), (11111110, 56),}