#include <iostream> #include <vector> #include <algorithm> #include <queue> using namespace std; vector<int> solve_degseq(vector<int> D) { int N = D.size(); if(N == 2) return {1,1}; if(N == 3 || D[3] == 1) { // bruteforce vector<int> d(N, 1); for(d[0] = 1; d[0] <= D[0]; d[0]++) for(d[1] = 1; d[1] <= D[1]; d[1]++) { d[2] = d[0]^d[1]^(1^N&1); if(d[2] > D[2]) continue; if(d[0] < d[1] || d[1] < d[2] || d[2] == 0) continue; if(d[0]+d[1] > 2+min(2,d[2])+(N-3)) continue; if(d[0]+d[1]+d[2] > 6+(N-3)) continue; if(d[0]+d[1]+d[2]+(N-3) < 2*(N-1)) continue; return d; } return {}; } // init. sequence int D_sum = 0; for(int i = 0; i < N; i++) D_sum += D[i]; vector<int> d_init(N); if(D_sum >= 5*N+4) { for(int i = 0; i < N; i++) { d_init[i] = 1; while(2*d_init[i] <= D[i]) d_init[i] *= 2; } int x = 0; for(int i = 0; i < N; i++) x ^= d_init[i]; for(int b = 16; b >= 1; b--) if((x>>b)&1) { for(int i = N-1; i >= 0; i--) if(d_init[i] == (1<<b)) { x ^= (1<<b)^(1<<(b-1)); d_init[i] = 1<<(b-1); break; } } if(x) { for(int i = 0; i < N; i++) if(d_init[i]%2 == 0 && d_init[i] < D[i]) { d_init[i]++; x = 0; break; } } if(x) { for(int i = N-1; i > 0; i--) if(d_init[i] == d_init[0]) { d_init[i] -= 2; d_init[i-1]--; x = 0; break; } } } else { vector< vector<int> > max_d_sum(N+1, vector<int>(2*N, -4*N)); max_d_sum[0][0] = 0; for(int i = 0; i < N; i++) for(int x = 0; x < 2*N; x++) if(max_d_sum[i][x] >= 0) for(int j = 1; j <= D[i]; j++) max_d_sum[i+1][x^j] = max(max_d_sum[i+1][x^j], max_d_sum[i][x]+j); if(max_d_sum[N][0] < 2*(N-1)) return {}; int x = 0, s = max_d_sum[N][0]; for(int i = N-1; i >= 0; i--) { for(int j = 1; j <= min(s,D[i]); j++) if(max_d_sum[i][x^j] == s-j) { s -= j; x ^= j; d_init[i] = j; break; } } sort(rbegin(d_init), rend(d_init)); } // valid sequence vector<int> lsb(N); for(int i = 1; i < N; i++) { lsb[i] = 0; while((i&(1<<lsb[i])) == 0) lsb[i]++; } vector<int> d = d_init; int B = 0; while((2<<B) < N) B++; vector< vector<int> > id_by_lsb(B+1); for(int i = 0; i < N; i++) if(d[i] > 1) id_by_lsb[lsb[d[i]]].push_back(i); int d_sum = 0; for(int i = 0; i < N; i++) d_sum += d[i]; while(d_sum > 2*(N-1)) { int b = -1; for(int i = 0; i <= B; i++) if((int)id_by_lsb[i].size() >= 2) { b = i; break; } bool sub1 = (b == -1 && d_sum > 2*N); if(sub1) { int id0 = id_by_lsb[0].back(); id_by_lsb[0].pop_back(); d[id0]--; id_by_lsb[lsb[d[id0]]].push_back(id0); for(int i = 0; i <= B; i++) if((int)id_by_lsb[i].size() >= 2) { b = i; break; } } if(b == -1) break; int id1 = id_by_lsb[b].back(); id_by_lsb[b].pop_back(); int id2 = id_by_lsb[b].back(); id_by_lsb[b].pop_back(); int s = sub1 ? 1 : min(d_sum/2-N+1, min(1<<b, min(d[id1],d[id2])-1)); d[id1] -= s, d[id2] -= s; if(d[id1] > 1) id_by_lsb[lsb[d[id1]]].push_back(id1); if(d[id2] > 1) id_by_lsb[lsb[d[id2]]].push_back(id2); if(sub1) { int id0 = id_by_lsb[0].back(); id_by_lsb[0].pop_back(); d[id0]--; id_by_lsb[lsb[d[id0]]].push_back(id0); d_sum -= 2+2*s; } else d_sum -= 2*s; } sort(rbegin(d), rend(d)); if(d[2] == 1 && d_sum == 2*N) d[2] = d[3] = 2; return d; } vector< vector<int> > construct(vector<int> d) { int N = d.size(); vector< pair<int,int> > ds(N); for(int i = 0; i < N; i++) ds[i] = {d[i], i}; vector< vector<int> > G(N); for(int i = 0; i < N-1; i++) { for(int j = 1; j <= ds[0].first; j++) { G[ds[0].second].push_back(ds[j].second); G[ds[j].second].push_back(ds[0].second); ds[j].first--; } vector< pair<int,int> > ds_nw(N-1-i); merge(rbegin(ds), rbegin(ds)+(N-1-i-ds[0].first), rbegin(ds)+(N-1-i-ds[0].first), rend(ds)-1, rbegin(ds_nw)); ds = ds_nw; } return G; } void DFS(int v, int v_prev, vector< vector<int> > & G, vector<char> & vis, pair<int, int> & e) { for(auto v_nxt : G[v]) if(v_nxt != v_prev) { if(vis[v_nxt]) { if(e.first == -1) e = {v, v_prev}; break; } vis[v_nxt] = 1; DFS(v_nxt, v, G, vis, e); } } pair<int,int> find_edge_on_cycle(vector< vector<int> > & G, int v_init) { int N = G.size(); vector<char> vis(N, 0); pair<int, int> e = {-1,-1}; vis[v_init] = 1; DFS(v_init, v_init, G, vis, e); return e; } vector< vector<int> > make_connected(vector< vector<int> > G) { int N = G.size(); vector<int> in_comp(N, -1), edges; vector< vector<int> > comp; int C = 0; for(int i = 0; i < N; i++) if(in_comp[i] == -1) { in_comp[i] = C; comp.push_back({i}); edges.push_back(0); static queue<int> q; q.push(i); while(!q.empty()) { for(auto v : G[q.front()]) if(in_comp[v] == -1) { in_comp[v] = C; comp.back().push_back(v); q.push(v); } q.pop(); } for(auto v : comp.back()) edges.back() += G[v].size(); C++; } while(C > 1) { pair<int,int> e1, e2; int c1 = 0; if(edges.back()+2 == 2*(int)comp.back().size()) { while(edges[c1]+2 == 2*(int)comp[c1].size()) c1++; e2 = {comp.back()[0], G[comp.back()[0]].back()}; e1 = find_edge_on_cycle(G, comp[c1][0]); } else { e2 = find_edge_on_cycle(G, comp.back()[0]); e1 = {comp[c1][0], G[comp[c1][0]].back()}; } replace(begin(G[e1.first]), end(G[e1.first]), e1.second, e2.second); replace(begin(G[e1.second]), end(G[e1.second]), e1.first, e2.first); replace(begin(G[e2.first]), end(G[e2.first]), e2.second, e1.second); replace(begin(G[e2.second]), end(G[e2.second]), e2.first, e1.first); for(auto v : comp.back()) in_comp[v] = c1; comp[c1].insert(end(comp[c1]), begin(comp.back()), end(comp.back())); edges[c1] += edges.back(); comp.pop_back(); edges.pop_back(); C--; } return G; } int main() { cin.sync_with_stdio(0); cin.tie(0); int T; cin >> T; while(T--) { int N; cin >> N; vector<int> D(N); for(int i = 0; i < N; i++) cin >> D[i]; vector< pair<int,int> > Ds(N); for(int i = 0; i < N; i++) Ds[i] = {D[i], i}; sort(rbegin(Ds), rend(Ds)); vector<int> id(N); for(int i = 0; i < N; i++) id[Ds[i].second] = i; for(int i = 0; i < N; i++) D[i] = Ds[i].first; auto d = solve_degseq(D); if(d.empty()) { cout << "NO\n"; continue; } cout << "YES\n"; auto G = construct(d); auto G_conn = make_connected(G); for(int i = 0; i < N; i++) { string s(N, '0'); for(auto v : G_conn[id[i]]) s[Ds[v].second] = '1'; cout << s << "\n"; } } }