#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const long long mod=(long long)1e9+7;
long long ans,cnt[3010][3010],n,s[3010],Now;
int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&Now);
		s[i]=s[i-1]+Now;
	}
	cnt[1][0]=1;
	for(int i=1;i<n;i++)
		for(int j=i;j>=1;j--)
		{
			Now=cnt[j][s[i]%(long long)j];
			cnt[j+1][s[i]%(long long)(j+1)]=(cnt[j+1][s[i]%(long long)(j+1)]+Now)%mod;
		}
	for(int j=1;j<=n;j++)
		ans=(ans+cnt[j][s[n]%(long long)j])%mod;
	printf("%lld",ans);
	return 0;
}

#include <bits/stdc++.h>

using namespace std;

const long long int MOD = 998244353;
int N,K;
int board[50][50];
long long int fact[51];
bool check1[50];
bool check2[50];
int uf[50];

int find(int x)
{
	if(uf[x] < 0)
	{
		return x;
	}
	return uf[x] = find(uf[x]);
}

bool merge(int x,int y)
{
	x = find(x);
	y = find(y);
	if(x==y)
	{
		return false;
	}
	uf[x] += uf[y];
	uf[y] = x;
	return true;
}

int main(void)
{
	cin.tie(0);
	ios::sync_with_stdio(false);

	/*
	vector <int> v = {1,2,3,4};
 
	queue <vector<int>> que;
	set <vector<int>> visited;
	visited.insert(v);
	que.push(v);
 
	while(!que.empty())
	{
		vector <int> now = que.front();
		que.pop();
 
		vector <int> next = now;
		int t = next[0];
		next[0] = next[1];
		next[1] = t;
		if(visited.find(next)==visited.end())
		{
			visited.insert(next);
			que.push(next);
		}
 		
		next = now;
		t = next[2];
		next[2] = next[3];
		next[3] = t;
		if(visited.find(next)==visited.end())
		{
			visited.insert(next);
			que.push(next);
		}

 		/*
		next = now;
		t = next[0];
		next[0] = next[3];
		next[3] = t;
		if(visited.find(next)==visited.end())
		{
			visited.insert(next);
			que.push(next);
		}

		next = now;
		t = next[1];
		next[1] = next[2];
		next[2] = t;
		if(visited.find(next)==visited.end())
		{
			visited.insert(next);
			que.push(next);
		}
							
	}
 
	cout << visited.size() << '\n';
 
	return 0;
	*/

	cin >> N >> K;

	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			cin >> board[i][j];
		}
	}
	fact[0] = 1;

	for(int i=1;i<=50;i++)
	{
		fact[i] = ((fact[i-1]%MOD)*(i%MOD)%MOD);
		fact[i]%=MOD;
	}

	long long int res = 1;
	memset(uf,-1,sizeof(uf));
	for(int i=0;i<N;i++)
	{
		for(int j=i+1;j<N;j++)
		{
			bool ok = true;
			for(int k=0;k<N;k++)
			{
				if(board[i][k] + board[j][k] > K)
				{
					ok = false;
					break;
				}
			}
			if(ok)
			{
				merge(i,j);
			}
		}
	}

	for(int i=0;i<N;i++)
	{
		if(uf[i] < 0)
		{
			res = ((res%MOD)*(fact[abs(uf[i])]%MOD)%MOD);
			res%=MOD;
		}
	}

	memset(uf,-1,sizeof(uf));

	for(int i=0;i<N;i++)
	{
		for(int j=i+1;j<N;j++)
		{
			bool ok = true;
			for(int k=0;k<N;k++)
			{
				if(board[k][i] + board[k][j] > K)
				{
					ok = false;
					break;
				}
			}
			if(ok)
			{
				merge(i,j);
			}
		}
	}

	for(int i=0;i<N;i++)
	{
		if(uf[i] < 0)
		{
			res = ((res%MOD)*(fact[abs(uf[i])]%MOD)%MOD);
			res%=MOD;
		}
	}

	cout << res << '\n';
	
	return 0;
}
