#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
#include <chrono>
#include <random>
#include <bitset>
#include <array>
using namespace std;
#ifdef LOCAL
#define eprintf(...) {fprintf(stderr, __VA_ARGS__);fflush(stderr);}
#else
#define eprintf(...) 42
#endif
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull = unsigned long long;
template<typename T>
using pair2 = pair<T, T>;
using pii = pair<int, int>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
return (ull)rng() % B;
}
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
clock_t startTime;
double getCurrentTime() {
return (double)(clock() - startTime) / CLOCKS_PER_SEC;
}
const int N = 2002;
int SUCC = 0;
int n;
pii ord[N];
int d[N];
int dp[N][2 * N + 3];
int par[N][2 * N + 3];
char g[N][N];
void printTree() {
int sum = 0;
int X = 0;
for (int i = 0; i < n; i++) {
sum += d[i];
X ^= d[i];
ord[i] = mp(d[i], i);
}
assert(X == 0);
assert(sum >= 2 * n - 2);
assert(sum < 2 * n + 6);
sort(ord, ord + n);
reverse(ord, ord + n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
g[i][j] = '0';
g[i][n] = '\0';
}
int p = 0;
vector<int> a = vector<int>();
if (sum != 2 * n - 2) {
sum = (sum - (2 * n - 2)) / 2;
assert(ord[3].first >= 3);
assert(ord[0].first >= 4);
sum += 3;
for (int i = 0; sum > 0 && i < 4; i++)
for (int j = i + 1; sum > 0 && j < 4; j++) {
int v = ord[i].second, u = ord[j].second;
g[v][u] = g[u][v] = '1';
d[v]--;
d[u]--;
sum--;
}
p = 4;
for (int i = 0; i < 4; i++) {
int v = ord[i].second;
for (int j = 0; j < d[v]; j++)
a.push_back(v);
}
} else {
p = 1;
for (int i = 0; i < 1; i++) {
int v = ord[i].second;
for (int j = 0; j < d[v]; j++)
a.push_back(v);
}
}
for (int i = p; i < n; i++) {
int v = ord[i].second;
assert(!a.empty());
int u = a.back();
a.pop_back();
g[v][u] = g[u][v] = '1';
for (int j = 1; j < d[v]; j++)
a.push_back(v);
}
printf("YES\n");
for (int i = 0; i < n; i++) {
printf("%s\n", g[i]);
}
SUCC++;
}
void reduceFour() {
int sum = 0, X = 0;
for (int i = 0; i < n; i++) {
sum += d[i];
X ^= d[i];
}
assert(X == 0);
assert(sum >= 2 * n - 2);
assert(sum < 3 * n);
while(sum >= 2 * n + 6) {
int k = 30;
for (int i = 0; i < n; i++) {
if (d[i] < 8) continue;
int x = (d[i] >> 2) << 2;
while(x & ((1 << k) - 1)) k--;
}
if (k < 30) {
int v = -1, u = -1;
for (int i = 0; i < n; i++) {
if (d[i] < 8) continue;
if (((d[i] >> k) & 1) == 0) continue;
if (v == -1) {
v = i;
} else if (u == -1) {
u = i;
}
}
assert(v != -1);
if (u != -1) {
sum -= 8;
d[v] -= 4;
d[u] -= 4;
continue;
}
assert(k == 2);
u = 0;
while(u < n && (d[u] < 4 || d[u] >= 8)) u++;
assert(u < n);
int x = d[v] ^ d[u] ^ 3;
assert(x < d[v]);
assert((d[v] - x) + (d[u] - 3) <= 8);
sum -= d[v] - x + d[u] - 3;
d[v] = x;
d[u] = 3;
continue;
}
int v = -1, u = -1;
for (int i = 0; i < n; i++) {
if (d[i] < 4) continue;
if ((d[i] & 2) == 0) continue;
if (v == -1) {
v = i;
} else if (u == -1) {
u = i;
}
}
if (u != -1) {
sum -= 4;
d[v] -= 2;
d[u] -= 2;
continue;
}
v = -1; u = -1;
for (int i = 0; i < n; i++) {
if (d[i] < 4) continue;
if ((d[i] & 1) == 0) continue;
if (v == -1) {
v = i;
} else if (u == -1) {
u = i;
}
}
if (u != -1) {
sum -= 2;
d[v] -= 1;
d[u] -= 1;
continue;
}
for (int i = 0; i < n; i++)
ord[i] = mp(d[i], i);
sort(ord, ord + n);
reverse(ord, ord + n);
int p = 0;
while(p < n && ord[p].first >= 4) p++;
assert(p % 2 == 0);
while(sum >= 2 * n + 6 && p > 0) {
p -= 2;
int v = ord[p].second, u = ord[p + 1].second;
int x = d[v] ^ d[u];
sum -= d[v] + d[u];
if (x == 3) {
d[v] = 2;
d[u] = 1;
} else {
d[v] = 3;
d[u] = 3 ^ x;
}
sum += d[v] + d[u];
}
return;
}
}
bool checkThree(int a, int b, int c, int ones, int twos) {
int sum = a + b + c + ones * 1 + twos * 2;
if (sum < 2 * n - 2) return false;
assert(sum % 2 == 0);
if (a < b) swap(a, b);
if (b < c) swap(b, c);
if (a < b) swap(a, b);
assert(a > 1);
if (b == 1) {
return true;
}
if (c == 1) {
if (twos > 0) {
c = 2;
ones++;
twos--;
}
}
if (c == 1) {
return sum == 2 * n - 2;
}
return (sum - (2 * n - 2)) / 2 <= 1 + twos;
}
void printThree() {
/*
eprintf("print 3\n");
for (int i = 0; i < n; i++)
eprintf("%d ", d[i]);
eprintf("\n");
*/
int sum = 0;
int X = 0;
for (int i = 0; i < n; i++) {
sum += d[i];
X ^= d[i];
ord[i] = mp(d[i], i);
}
assert(X == 0);
assert(sum >= 2 * n - 2);
sort(ord, ord + n);
reverse(ord, ord + n);
assert(ord[3].first <= 2);
if (ord[0].first == 2) {
if (sum == 2 * n) {
d[ord[0].second] = d[ord[1].second] = 1;
sum -= 2;
}
}
if (sum == 2 * n - 2) {
printTree();
return;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++)
g[i][j] = '0';
g[i][n] = '\0';
}
int A = ord[0].second, B = ord[1].second, C = ord[2].second;
sum = (sum - (2 * n - 2)) / 2;
assert(sum > 0);
assert(d[C] >= 2);
g[A][B] = g[B][A] = g[A][C] = g[C][A] = g[B][C] = g[C][B] = '1';
d[A] -= 2;
d[B] -= 2;
d[C] -= 2;
sum--;
int p = 3;
while(sum > 1) {
assert(p < n);
int v = ord[p++].second;
assert(d[v] == 2);
if (d[A] < d[B]) swap(A, B);
if (d[B] < d[C]) swap(B, C);
if (d[A] < d[B]) swap(A, B);
assert(d[A] + d[B] >= 2);
if (d[B] == 0) {
assert(p < n);
int u = ord[p++].second;
assert(d[u] == 2);
g[A][v] = g[v][A] = g[A][u] = g[u][A] = g[v][u] = g[u][v] = '1';
d[A] -= 2;
d[v] -= 2;
d[u] -= 2;
sum--;
} else {
g[A][v] = g[B][v] = g[v][A] = g[v][B] = '1';
sum--;
d[A]--;
d[B]--;
d[v] -= 2;
}
}
if (d[A] < d[B]) swap(A, B);
if (d[B] < d[C]) swap(B, C);
if (d[A] < d[B]) swap(A, B);
if (p < n && ord[p].first == 2) {
int v = ord[p].second;
d[A]--;
g[A][v] = g[v][A] = '1';
p++;
while(p < n && ord[p].first == 2) {
int u = ord[p++].second;
g[v][u] = g[u][v] = '1';
v = u;
}
if (sum == 0) {
assert(p < n);
int u = ord[p++].second;
g[v][u] = g[u][v] = '1';
} else {
if (d[B] > 0) {
d[B]--;
g[B][v] = g[v][B] = '1';
} else {
assert(d[A] > 0);
d[A]--;
g[A][v] = g[v][A] = '1';
}
}
}
while(p < n) {
int v = ord[p].second;
assert(d[v] == 1);
if (d[B] > 0) swap(A, B);
if (d[C] > 0) swap(A, C);
assert(d[A] > 0);
d[A]--;
g[A][v] = g[v][A] = '1';
p++;
}
printf("YES\n");
for (int i = 0; i < n; i++) {
printf("%s\n", g[i]);
}
SUCC++;
}
void solve() {
//eprintf("SOLVE\n");
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &ord[i].first);
ord[i].second = i;
}
if (n == 2) {
printf("YES\n01\n10\n");
SUCC++;
return;
}
if (n == 3) {
printf("NO\n");
return;
}
sort(ord, ord + n);
reverse(ord, ord + n);
int ones = 0;
while(ones < n - 3 && ord[n - 1 - ones].first == 1) ones++;
int twos = n - 3 - ones;
for (int x = 0; x <= 1 && x <= twos; x++) {
int nones = ones + x, ntwos = twos - x;
int X = (nones & 1) ^ ((ntwos & 1) << 1);
for (int c = 1; c <= ord[2].first; c++)
for (int b = 1; b <= ord[1].first; b++) {
int a = b ^ c ^ X;
if (a == 0 || a > ord[0].first) continue;
if (!checkThree(a, b, c, nones, ntwos)) continue;
d[ord[0].second] = a;
d[ord[1].second] = b;
d[ord[2].second] = c;
for (int i = 3; i < n - nones; i++)
d[ord[i].second] = 2;
for (int i = n - nones; i < n; i++)
d[ord[i].second] = 1;
printThree();
return;
}
}
if (ord[3].first <= 2) {
printf("NO\n");
return;
}
int sum = 0;
for (int i = 0; i < n; i++)
sum += ord[i].first;
if (sum >= 3 * n) {
for (int i = 0; i + 1 < n; i += 2)
ord[i].first = ord[i + 1].first;
if (n & 1) {
ord[n - 1].first = 1;
if (ord[0].first % 2 == 0) {
ord[0].first--;
ord[1].first--;
}
ord[0].first--;
}
sum = 0;
for (int i = 0; i < n; i++)
sum += ord[i].first;
assert(sum >= 2 * n - 2);
assert(sum % 2 == 0);
for (int i = 0; i + 1 < n; i += 2) {
int x = (ord[i].first - 1);
x = min(x, (sum - (2 * n - 2)) / 2);
if ((n & 1) && i == 0) x -= x & 1;
sum -= 2 * x;
ord[i].first -= x;
ord[i + 1].first -= x;
}
assert(sum == 2 * n - 2);
for (int i = 0; i < n; i++)
d[ord[i].second] = ord[i].first;
printTree();
} else {
for (int i = 0; i <= n; i++)
for (int x = 0; x < 2 * ord[0].first; x++)
dp[i][x] = -1;
dp[n][0] = 0;
for (int i = n - 1; i >= 0; i--)
for (int x = 0; x < 2 * ord[i].first; x++) {
if (dp[i + 1][x] == -1) continue;
for (int y = (i <= 3 ? 3 : 1); y <= ord[i].first; y++) {
int z = x ^ y;
int w = dp[i + 1][x] + y;
if (w <= dp[i][z]) continue;
dp[i][z] = w;
par[i][z] = y;
}
}
if (dp[0][0] < 2 * n - 2) {
printf("NO\n");
return;
}
int z = 0;
for (int p = 0; p < n; p++) {
int x = par[p][z];
d[ord[p].second] = x;
z ^= x;
}
reduceFour();
bool all3 = true;
int sum = 0;
for (int i = 0; i < n; i++) {
all3 &= d[i] <= 3;
sum += d[i];
}
assert(sum >= 2 * n - 2);
if (all3) {
sum = (sum - (2 * n - 2)) / 2;
int L3 = -1, L2 = -1;
for (int i = 0; sum > 0 && i < n; i++) {
if (d[i] == 1) continue;
if (d[i] == 2) {
if (L2 == -1) {
L2 = i;
} else {
d[i]--;
d[L2]--;
sum--;
L2 = -1;
}
} else if (d[i] == 3) {
if (L3 == -1) {
L3 = i;
} else {
d[i]--;
d[L3]--;
sum--;
if (sum == 0) break;
d[i]--;
d[L3]--;
sum--;
L3 = -1;
}
} else assert(false);
}
assert(sum == 0);
} else {
assert(sum < 2 * n + 6);
}
printTree();
}
}
int main()
{
startTime = clock();
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
int t;
scanf("%d", &t);
while(t--) {
solve();
}
fprintf(stderr, "YES = %d\n", SUCC);
return 0;
}