#include <bits/stdc++.h>
using namespace std;
#define int long long
const int INF = 1e12;
int comb2(int x)
{
return x * (x-1) / 2;
}
int n,m;
bool verif(vector<int> v)
{
int pref = 0;
for(int i=1;i<=n;i++)
{
if(i > 1 && v[i-1] > v[i])
return 0;
pref += v[i];
if(pref < comb2(i))
return 0;
}
if(pref != comb2(n))
return 0;
return 1;
}
int calc(vector<int> v)
{
int tot = 0;
for(int i=1;i<=n;i++)
tot += comb2(v[i]);
return tot;
}
bool done;
vector<int> sol;
void recursiv(vector<int> newv)
{
/*if(visited[v])
return;
visited[v] = 1;*/
while(1)
{
int mycalc = calc(newv);
if(mycalc == m)
{
done = 1;
sol = newv;
return;
}
int curdist = abs(mycalc - m);
int closest = curdist;
bool easy = (mycalc > (m + n));
pair<int,int> unde = {-1, -1};
int best_from = n, best_to = 1;
while(best_from >= 1 && newv[best_from] == newv[best_from - 1])
best_from--;
while(best_to <= n && newv[best_to + 1] == newv[best_to])
best_to++;
if(best_to < best_from)
{
int to = best_to, from = best_from;
newv[from]--;
newv[to]++;
if(newv[from] >= newv[from-1] && newv[to] <= newv[to+1] /*&& verif(newv)*/)
{
newv[from]++;
newv[to]--;
int newdist = mycalc - newv[from] + 1 + newv[to];
int mydist = abs(newdist - m);
if(mydist < closest)
{
closest = mydist;
unde = {from, to};
}
}
else
{
newv[from]++;
newv[to]--;
}
}
if(unde.first != -1)
{
newv[unde.first]--;
newv[unde.second]++;
continue;
}
for(int lun=n-1;lun>=1;lun--)
{
bool found = 0;
for(int to=1;to+lun<=n;to++)
{
int from = to + lun;
newv[from]--;
newv[to]++;
if(newv[from] >= newv[from-1] && newv[to] <= newv[to+1] /*&& verif(newv)*/)
{
newv[from]++;
newv[to]--;
int newdist = mycalc - newv[from] + 1 + newv[to];
int mydist = abs(newdist - m);
if(mydist < closest)
{
closest = mydist;
unde = {from, to};
found = 1;
}
}
else
{
newv[from]++;
newv[to]--;
}
}
if(easy && found)
break;
}
if(unde.first == -1)
return;
newv[unde.first]--;
newv[unde.second]++;
}
}
int mat[5005][5005];
void reconstruct(vector<int> v)
{
assert(verif(v));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
mat[i][j] = 0;
vector<pair<int,int>> aux;
for(int i=1;i<=n;i++)
aux.push_back({v[i], i});
while(!aux.empty())
{
sort(aux.begin(), aux.end());
if(aux.back().first == 0)
break;
assert(aux.back().first > 0);
for(int i=0;i<aux.back().first;i++)
{
mat[aux.back().second][aux[i].second] = 1;
}
for(int i=aux.back().first;i<(int)aux.size()-1;i++)
{
aux[i].first--;
mat[aux[i].second][aux.back().second] = 1;
}
aux.back().first = 0;
aux.pop_back();
}
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
assert(mat[i][j] + mat[j][i] == 1);
if(mat[i][j] + mat[j][i] != 1)
{
//cerr<<i<<" "<<j<<": "<<mat[i][j]<<" & "<<mat[j][i]<<" zzz\n";
}
}
}
for(int i=2;i<=n;i++)
{
for(int j=1;j<i;j++)
cout<<mat[i][j];
cout<<"\n";
}
}
void solve()
{
cin>>n>>m;
m = n * (n-1) * (n-2) / 6 - m;
//get close to m then do backtrack
done = 0;
vector<int> init(n+2,0);
for(int i=1;i<=n;i++)
init[i] = i - 1;
assert(verif(init));
if(m > calc(init))
{
cout<<"No\n";
return;
}
recursiv(init);
if(!done)
{
cout<<"No\n";
return;
}
assert(calc(sol) == m);
//for(int i=1;i<=n;i++) cerr<<sol[i]<<" ";cerr<<"sol\n";
cout<<"Yes\n";
reconstruct(sol);
}
signed main()
{
ios_base::sync_with_stdio(0);cin.tie(0);
int t;
cin>>t;
while(t--)
solve();
return 0;
}
/*
for each "bad" tuple (x,y,z) of nodes,
exactly one of x,y,z will have outgoing edges towards the other 2
=> M = total - sum(comb(cnt_outgoing(x), 2))
*/