- #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";
- }
- }
- }