#define NguyenDangQuan the_author

#include <bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define mset(x, i) memset(x,i,sizeof(x))
#define elif else if
#define heap priority_queue
#define fi first
#define se second
#define pb push_back
#define ld long double
#define ll long long
#define ull unsigned long long
using namespace std;

int typetest;

inline void fastIOfileinput(){
	ios_base:: sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	typetest = 1;
}

const int N = 2e5 + 2;
ll l, r, m;

void Enter(){
	cin >> l >> r >> m;
}

void solve(){
	ll n = (m + r) / l - 1;
	if(n < (m + l) / r - 1)
		++n;
	//cout << n << "\n";
	ll a = (m + l) / n;
	ll b = (m + l) % n;
	ll c = l;
	while(c <= r && a < l)
		c += n,
		++a;
	if(c > r)
		c -= n,
		--a;
	while(b < l && a > l)
		b += n,
		--a;
	while(c < r && b < l)
		++c,
		++b;
	cout << a << " " << b << " " << c << "\n";
}

signed main(){
	fastIOfileinput();
	if(typetest){
		int t;
		cin >> t;
		while(t--){
			Enter();
			solve();
		}
	}
	else{
		Enter();
		solve();
	}
}


#define NguyenDangQuan the_author

#include <bits/stdc++.h>
#define all(x) x.begin(),x.end()
#define mset(x, i) memset(x,i,sizeof(x))
#define elif else if
#define heap priority_queue
#define fi first
#define se second
#define pb push_back
#define ld long double
#define ll long long
#define ull unsigned long long
using namespace std;

int typetest;

inline void fastIOfileinput(){
	ios_base:: sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	typetest = 1;
}

const int N = 2e5 + 2;
ll l, r, m;

void Enter(){
	cin >> l >> r >> m;
}

void solve(){
	if(m >= l && m <= r){
		cout << m << " " << l << " " << l << "\n";
		return;
	}
	for(ll a = l; a <= r; ++a){
		if(m >= a){
			ll n = m / a;
			ll q = m % a;
			ll c = l;
			ll b = c + q;
			if(b >= l && b <= r){
				cout << a << " " << b << " " << c << "\n";
				return;
			}
		}
		else if(a - m + l <= r){
			cout << a << " " << l << " " <<  a - m + l << "\n";
			return;
		}
	}
}

signed main(){
	fastIOfileinput();
	if(typetest){
		int t;
		cin >> t;
		while(t--){
			Enter();
			solve();
		}
	}
	else{
		Enter();
		solve();
	}
}


// ~/SolverToBe/Developers/Corvus
// ~/sudo apt-get verdict Accpeted

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <functional>
#include <assert.h>
#include <complex>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int N = 200005, M = 505;
const ll MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);

struct polynomial {
	int sz, i;
	polynomial() {}
	polynomial(int s, int i) {
		this->sz = s;
		this->i = i;
	}
	bool operator<(const polynomial &o) const {
		if (sz != o.sz)
			return sz > o.sz;
		return i < o.sz;
	}
};

int n, m, k, c[N];
vector<int> poly[N];

const int mod = 1009;
const int root = 11;

int fast_pow(int b, int n) {
	if (n == 0) return 1;
	if (n == 1) return b;
	if (n & 1) return (b * fast_pow(b, n - 1)) % mod;
	int r = fast_pow(b, n / 2);
	return (r*r) % mod;
}

void fft(vector<int> &p, bool inverse) {
	int n = p.size();
	int h = fast_pow(root, (mod - 1) / n);
	if (inverse) h = fast_pow(h, mod - 2);
	for (int i = 1, j = 0; i < n - 1; i++) {
		for (int bit = n >> 1; bit > (j ^= bit); bit >>= 1);
		if (i < j) swap(p[i], p[j]);
	}
	for (int len = 1; len < n; len <<= 1) {
		int wlen = fast_pow(h, n / (len << 1));
		int w = 1;
		for (int i = 0; i < len; i++) {
			for (int j = i; j < n; j += (len << 1)) {
				int u = p[j], v = (p[j + len] * w) % mod;
				p[j] = u + v;
				if (p[j] >= mod) p[j] -= mod;
				p[j + len] = u - v;
				if (p[j + len] < 0) p[j + len] += mod;
			}
			w = (w * wlen) % mod;
		}
	}
	if (inverse) {
		int n_inverse = fast_pow(n, mod - 2);
		for (int i = 0; i < p.size(); i++)
			p[i] = (p[i] * n_inverse) % mod;
	}
}

vector<int> multiply(vector<int> &a, vector<int> &b) {
	int n = 1;
	while (n < a.size() + b.size())
		n <<= 1;
	a.resize(n), b.resize(n);
	fft(a, 0), fft(b, 0);
	for (int i = 0; i < n; i++)
		a[i] = (a[i] * b[i]) % mod;
	fft(a, 1);
	return a;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
#endif
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 0, x; i < n; i++) {
		scanf("%d", &x);
		x--;
		c[x]++;
	}
	priority_queue<polynomial> pq;
	for (int i = 0; i < m; i++) {
		poly[i].resize(c[i] + 1, 1);
		pq.push(polynomial(poly[i].size(), i));
	}
	while (pq.size() >= 2) {
		polynomial a = pq.top(); pq.pop();
		polynomial b = pq.top(); pq.pop();
		poly[a.i] = multiply(poly[a.i], poly[b.i]);
		poly[a.i].resize(a.sz + b.sz);
		pq.push(polynomial(poly[a.i].size(), a.i));
	}
	polynomial p = pq.top();
	if (poly[p.i].size() <= k) {
		puts("0");
		return 0;
	}
	printf("%d\n", poly[p.i][k]);
	return 0;
}


// ~/SolverToBe/Developers/Corvus
// ~/sudo apt-get verdict Accpeted

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <functional>
#include <assert.h>
#include <complex>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int N = 200005, M = 505;
const ll MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);

struct polynomial {
	int sz, i;
	polynomial() {}
	polynomial(int s, int i) {
		this->sz = s;
		this->i = i;
	}
	bool operator<(const polynomial &o) const {
		if (sz != o.sz)
			return sz > o.sz;
		return i < o.sz;
	}
};

int n, m, k, c[N];
vector<int> poly[N];

const int mod = 1009;

void fft(vector<complex<double> > & p, bool inverse) {
	int n = p.size();
	for (int i = 1, j = 0; i < n - 1; i++) {
		for (int bit = n >> 1; bit > (j ^= bit); bit >>= 1);
		if (i < j) swap(p[i], p[j]);
	}
	for (int len = 2; len <= n; len <<= 1) {
		double ang = (inverse ? -1 : 1) * 2 * PI / len;
		complex<double> Wlen(cos(ang), sin(ang));
		for (int i = 0; i < n; i += len) {
			complex<double> W(1);
			for (int j = 0; j < (len >> 1); j++) {
				complex <double> u = p[i + j], v = p[i + j + (len >> 1)] * W;
				p[i + j] = u + v;
				p[i + j + (len >> 1)] = u - v;
				W *= Wlen;
			}
		}
	}
	if (inverse)
		for (int i = 0; i < n; i++)
			p[i] /= n;
}

vector<int> multiply(vector<int> &a, vector<int> &b) {
	vector<complex<double> > fa(a.begin(), a.end()), fb(b.begin(), b.end());
	int n = 1;
	while (n < a.size() + b.size())
		n <<= 1;
	fa.resize(n), fb.resize(n);
	fft(fa, 0), fft(fb, 0);
	for (int i = 0; i < n; i++)
		fa[i] *= fb[i];
	fft(fa, 1);
	vector<int> res(n);
	for (int i = 0; i < n; i++)
		res[i] = ll(round(fa[i].real())) % mod;
	return res;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
#endif
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 0, x; i < n; i++) {
		scanf("%d", &x);
		x--;
		c[x]++;
	}
	priority_queue<polynomial> pq;
	for (int i = 0; i < m; i++) {
		if (!c[i]) continue;
		poly[i].resize(c[i] + 1, 1);
		pq.push(polynomial(c[i], i));
	}
	while (pq.size() >= 2) {
		polynomial a = pq.top(); pq.pop();
		polynomial b = pq.top(); pq.pop();
		poly[a.i] = multiply(poly[a.i], poly[b.i]);
		poly[a.i].resize(a.sz + b.sz + 1);
		pq.push(polynomial(poly[a.i].size() - 1, a.i));
	}
	polynomial p = pq.top();
	if (poly[p.i].size() <= k) {
		puts("0");
		return 0;
	}
	printf("%d\n", poly[p.i][k]);
	return 0;
}


// ~/SolverToBe/Developers/Corvus
// ~/sudo apt-get verdict Accpeted

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <functional>
#include <assert.h>
#include <complex>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int N = 200005, M = 505;
const ll MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);

struct polynomial {
	int sz, i;
	polynomial() {}
	polynomial(int s, int i) {
		this->sz = s;
		this->i = i;
	}
	bool operator<(const polynomial &o) const {
		if (sz != o.sz)
			return sz > o.sz;
		return i < o.sz;
	}
};

int n, m, k, c[N];
vector<int> poly[N];

const int mod = 1009;
const int root = 11;

int fast_pow(int b, int n) {
	if (n == 0) return 1;
	if (n == 1) return b;
	if (n & 1) return (b * fast_pow(b, n - 1)) % mod;
	int r = fast_pow(b, n / 2);
	return (r*r) % mod;
}

void fft(vector<int> &p, bool inverse) {
	int n = p.size();
	int h = fast_pow(root, (mod - 1) / n);
	if (inverse) h = fast_pow(h, mod - 2);
	for (int i = 1, j = 0; i < n - 1; i++) {
		for (int bit = n >> 1; bit > (j ^= bit); bit >>= 1);
		if (i < j) swap(p[i], p[j]);
	}
	for (int len = 1; len < n; len <<= 1) {
		int wlen = fast_pow(h, n / (len << 1));
		int w = 1;
		for (int i = 0; i < len; i++) {
			for (int j = i; j < n; j += (len << 1)) {
				int u = p[j], v = (p[j + len] * w) % mod;
				p[j] = u + v;
				if (p[j] >= mod) p[j] -= mod;
				p[j + len] = u - v;
				if (p[j + len] < 0) p[j + len] += mod;
			}
			w = (w * wlen) % mod;
		}
	}
	if (inverse) {
		int n_inverse = fast_pow(n, mod - 2);
		for (int i = 0; i < p.size(); i++)
			p[i] = (p[i] * n_inverse) % mod;
	}
}

vector<int> multiply(vector<int> &a, vector<int> &b) {
	int n = 1;
	while (n < a.size() + b.size())
		n <<= 1;
	a.resize(n), b.resize(n);
	fft(a, 0), fft(b, 0);
	for (int i = 0; i < n; i++)
		a[i] = (a[i] * b[i]) % mod;
	fft(a, 1);
	return a;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
#endif
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 0, x; i < n; i++) {
		scanf("%d", &x);
		x--;
		c[x]++;
	}
	priority_queue<polynomial> pq;
	for (int i = 0; i < m; i++) {
		poly[i].resize(c[i] + 1, 1);
		pq.push(polynomial(poly[i].size(), i));
	}
	while (pq.size() >= 2) {
		polynomial a = pq.top(); pq.pop();
		polynomial b = pq.top(); pq.pop();
		poly[a.i] = multiply(poly[a.i], poly[b.i]);
		pq.push(polynomial(poly[a.i].size(), a.i));
	}
	polynomial p = pq.top();
	if (poly[p.i].size() <= k) {
		puts("0");
		return 0;
	}
	printf("%d\n", poly[p.i][k]);
	return 0;
}


// ~/SolverToBe/Developers/Corvus
// ~/sudo apt-get verdict Accpeted

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <functional>
#include <assert.h>
#include <complex>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int N = 200005, M = 505;
const ll MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);

struct polynomial {
	int sz, i;
	polynomial() {}
	polynomial(int s, int i) {
		this->sz = s;
		this->i = i;
	}
	bool operator<(const polynomial &o) const {
		if (sz != o.sz)
			return sz > o.sz;
		return i < o.sz;
	}
};

int n, m, k, c[N];
vector<int> poly[N];

const int mod = 1009;

void fft(vector<complex<double> > & v, bool inverse) {
	int n = v.size();
	if (n == 1) return;
	vector<complex<double> > v0(n / 2), v1(n / 2);
	for (int i = 0; 2 * i < n; i++) {
		v0[i] = v[2 * i];
		v1[i] = v[2 * i + 1];
	}
	fft(v0, inverse);
	fft(v1, inverse);
	double ang = (inverse ? -1 : 1) * 2 * PI / n;
	complex<double>  W(1), Wn(cos(ang), sin(ang));
	for (int i = 0; 2 * i < n; i++) {
		v[i] = v0[i] + W * v1[i];
		v[i + n / 2] = v0[i] - W * v1[i];
		if (inverse) v[i] /= 2, v[i + n / 2] /= 2;
		W *= Wn;
	}
}

vector<int> multiply(vector<int> &a, vector<int> &b) {
	vector<complex<double> > fa(a.begin(), a.end()), fb(b.begin(), b.end());
	int n = 1;
	while (n < a.size() + b.size())
		n *= 2;
	fa.resize(n);
	fb.resize(n);
	fft(fa, 0), fft(fb, 0);
	for (int i = 0; i < n; i++)
		fa[i] *= fb[i];
	fft(fa, 1);
	vector<int> res(n);
	for (int i = 0; i < n; i++) {
		res[i] = ll(round(fa[i].real())) % mod;
		if (res[i] < 0) res[i] += mod;
	}
	return res;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
#endif
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 0, x; i < n; i++) {
		scanf("%d", &x);
		x--;
		c[x]++;
	}
	priority_queue<polynomial> pq;
	for (int i = 0; i < m; i++) {
		if (!c[i]) continue;
		c[i] %= mod;
		poly[i].resize(c[i] + 1, 1);
		pq.push(polynomial(poly[i].size(), i));
	}
	while (pq.size() >= 2) {
		polynomial a = pq.top(); pq.pop();
		polynomial b = pq.top(); pq.pop();
		poly[a.i] = multiply(poly[a.i], poly[b.i]);
		if(poly[a.i].size())
			pq.push(polynomial(poly[a.i].size(), a.i));
	}
	polynomial p = pq.top();
	if (poly[p.i].size() <= k) {
		puts("0");
		return 0;
	}
	printf("%d\n", poly[p.i][k]);
	return 0;
}


// ~/SolverToBe/Developers/Corvus
// ~/sudo apt-get verdict Accpeted

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <functional>
#include <assert.h>
#include <complex>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int N = 200005, M = 505;
const ll MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);

struct polynomial {
	int sz, i;
	polynomial() {}
	polynomial(int s, int i) {
		this->sz = s;
		this->i = i;
	}
	bool operator<(const polynomial &o) const {
		if (sz != o.sz)
			return sz > o.sz;
		return i < o.sz;
	}
};

int n, m, k, c[N];
vector<int> poly[N];

const int mod = 1009;
const int root = 11;

int fast_pow(int b, int n) {
	if (n == 0) return 1;
	if (n == 1) return b;
	if (n & 1) return (b * fast_pow(b, n - 1)) % mod;
	int r = fast_pow(b, n / 2);
	return (r*r) % mod;
}

void fft(vector<complex<double> > & v, bool inverse) {
	int n = v.size();
	if (n == 1)
		return;

	vector<complex<double> > v0(n / 2), v1(n / 2);
	for (int i = 0; 2 * i < n; i++) {
		v0[i] = v[2 * i];
		v1[i] = v[2 * i + 1];
	}

	fft(v0, inverse);
	fft(v1, inverse);

	double ang = (inverse ? -1 : 1) * 2 * PI / n;
	complex<double>  W(1), Wn(cos(ang), sin(ang));

	for (int i = 0; 2 * i < n; i++) {
		v[i] = v0[i] + W * v1[i];
		v[i + n / 2] = v0[i] - W * v1[i];
		if (inverse) v[i] /= 2, v[i + n / 2] /= 2;
		W *= Wn;
	}
}

vector<int> multiply(vector<int> &a, vector<int> &b) {
	vector<complex<double> > fa(a.begin(), a.end()), fb(b.begin(), b.end());
	int n = 1;
	while (n < a.size() + b.size())
		n *= 2;
	fa.resize(n);
	fb.resize(n);

	fft(fa, 0), fft(fb, 0);

	for (int i = 0; i < n; i++)
		fa[i] *= fb[i];

	fft(fa, 1);

	vector<int> res(n);
	for (int i = 0; i < n; i++)
		res[i] = int(round(fa[i].real()))%mod;

	return res;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
#endif
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 0, x; i < n; i++) {
		scanf("%d", &x);
		x--;
		c[x]++;
	}
	priority_queue<polynomial> pq;
	for (int i = 0; i < m; i++) {
		if (!c[i]) continue;
		poly[i].resize(c[i] + 1, 1);
		pq.push(polynomial(poly[i].size(), i));
	}
	while (pq.size() >= 2) {
		polynomial a = pq.top(); pq.pop();
		polynomial b = pq.top(); pq.pop();
		poly[a.i] = multiply(poly[a.i], poly[b.i]);
		if(poly[a.i].size())
			pq.push(polynomial(poly[a.i].size(), a.i));
	}
	polynomial p = pq.top();
	if (poly[p.i].size() <= k) {
		puts("0");
		return 0;
	}
	printf("%d\n", poly[p.i][k]);
	return 0;
}


// ~/SolverToBe/Developers/Corvus
// ~/sudo apt-get verdict Accpeted

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <memory.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <functional>
#include <assert.h>
#include <complex>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

const int N = 200005, M = 505;
const ll MOD = 1e9 + 7;
const double eps = 1e-9;
const double PI = acos(-1.0);

struct polynomial {
	int sz, i;
	polynomial() {}
	polynomial(int s, int i) {
		this->sz = s;
		this->i = i;
	}
	bool operator<(const polynomial &o) const {
		if (sz != o.sz)
			return sz > o.sz;
		return i < o.sz;
	}
};

int n, m, k, c[N];
vector<int> poly[N];

const int mod = 1009;

void fft(vector<complex<double> > & v, bool inverse) {
	int n = v.size();
	if (n == 1) return;
	vector<complex<double> > v0(n / 2), v1(n / 2);
	for (int i = 0; 2 * i < n; i++) {
		v0[i] = v[2 * i];
		v1[i] = v[2 * i + 1];
	}
	fft(v0, inverse);
	fft(v1, inverse);
	double ang = (inverse ? -1 : 1) * 2 * PI / n;
	complex<double>  W(1), Wn(cos(ang), sin(ang));
	for (int i = 0; 2 * i < n; i++) {
		v[i] = v0[i] + W * v1[i];
		v[i + n / 2] = v0[i] - W * v1[i];
		if (inverse) v[i] /= 2, v[i + n / 2] /= 2;
		W *= Wn;
	}
}

vector<int> multiply(vector<int> &a, vector<int> &b) {
	vector<complex<double> > fa(a.begin(), a.end()), fb(b.begin(), b.end());
	int n = 1;
	while (n < a.size() + b.size())
		n *= 2;
	fa.resize(n);
	fb.resize(n);
	fft(fa, 0), fft(fb, 0);
	for (int i = 0; i < n; i++)
		fa[i] *= fb[i];
	fft(fa, 1);
	vector<int> res(n);
	for (int i = 0; i < n; i++) {
		res[i] = int(round(fa[i].real())) % mod;
		if (res[i] < 0) res[i] += mod;
	}
	return res;
}

int main() {
#ifndef ONLINE_JUDGE
	freopen("input.in", "r", stdin);
#endif
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 0, x; i < n; i++) {
		scanf("%d", &x);
		x--;
		c[x]++;
	}
	priority_queue<polynomial> pq;
	for (int i = 0; i < m; i++) {
		if (!c[i]) continue;
		poly[i].resize(c[i] + 1, 1);
		pq.push(polynomial(poly[i].size(), i));
	}
	while (pq.size() >= 2) {
		polynomial a = pq.top(); pq.pop();
		polynomial b = pq.top(); pq.pop();
		poly[a.i] = multiply(poly[a.i], poly[b.i]);
		if(poly[a.i].size())
			pq.push(polynomial(poly[a.i].size(), a.i));
	}
	polynomial p = pq.top();
	if (poly[p.i].size() <= k) {
		puts("0");
		return 0;
	}
	printf("%d\n", poly[p.i][k]);
	return 0;
}


#pragma GCC optimize("O3")
//#pragma GCC target("arch=native,tune=native")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

// Undefined sign for negative inputs
template<typename T>
static T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

// m must be positive
template<typename T>
static T mod(T a, T m)
{
    a %= m;
    if (a < 0)
        a += m;
    return a;
}

// a must be relatively prime to m
template<typename T>
static T inverse(T a, T m)
{
    a = mod(a, m);
    if (a <= 1)
        return a;
    return mod((1 - inverse(m, a) * m) / a, m);
}

template<typename T, typename C, T Modulus>
class MR
{
private:
    struct tag_plus {}; // indicates value is in range [0, 2 * Modulus)
    struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
    struct tag_good {}; // indicates value is in range

    T value;

    static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0, "compute type is too small");
    static_assert(Modulus < std::numeric_limits<T>::max() / 2, "storage type is too small");

    void reduce(tag_plus)
    {
        if (value >= Modulus)
            value -= Modulus;
    }

    void reduce(tag_minus)
    {
        if (value < 0)
            value += Modulus;
    }

    void reduce(tag_good) {}

public:
    typedef T value_type;
    typedef C compute_type;
    static const T modulus = Modulus;

    MR() : value(0) {}
    MR(C value) : value(value % Modulus) { reduce(tag_minus()); }
    template<typename tag_t>
    MR(T value, tag_t tag) : value(value) { reduce(tag); }

    MR &operator=(C value) { this->value = value % Modulus; reduce(tag_minus()); return *this; }

    MR operator +(MR b) const { return MR(value + b.value, tag_plus()); }
    MR operator -(MR b) const { return MR(value - b.value, tag_minus()); }
    MR operator *(MR b) const { return MR(C(value) * C(b.value) % Modulus, tag_good()); }
    MR operator -() const { return MR(-value, tag_minus()); }

    MR &operator +=(MR b) { value += b.value; reduce(tag_plus()); return *this; }
    MR &operator -=(MR b) { value -= b.value; reduce(tag_minus()); return *this; }
    MR &operator *=(MR b) { value = C(value) * C(b.value) % Modulus; return *this; }

    bool operator==(MR b) const { return value == b.value; }
    bool operator!=(MR b) const { return value != b.value; }

    T get() const { return value; }

    // These are only valid if the Modulus is prime, or at least if
    // the dividend is relatively prime to the modulus
    MR inverse() const
    {
        assert(value);
        return MR(::inverse(C(value), C(Modulus)), tag_good());
    }
    MR operator /(MR b) const { return *this * b.inverse(); }
    MR &operator /=(MR b) { return *this *= b.inverse(); }
};

template<typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr)
{
    return o << mr.get();
}

template<typename Traits>
class FFT
{
public:
    typedef typename Traits::type type;

private:
    template<typename It>
    static It fft_r(It first, It last, It tmp_first, It tmp_last, type g)
    {
        std::size_t S = last - first;
        if (S == 1)
            return first;
        else if (S == 2)
        {
            type a = *first;
            type b = *(first + 1);
            *first = a + b;
            *(first + 1) = a - b;
            return first;
        }
        std::size_t H = S / 2;
        It even = tmp_first;
        It odd = tmp_first + H;
        for (std::size_t i = 0; i < H; i++)
        {
            *(even + i) = *(first + 2 * i);
            *(odd + i) = *(first + 2 * i + 1);
        }
        type g2 = g * g;
        even = fft_r(even, odd, first, first + H, g2);
        odd = fft_r(odd, tmp_last, first, first + H, g2);
        if (&*even == &*first)
        {
            swap(first, tmp_first);
            swap(last, tmp_last);
        }
        type p = 1;
        for (std::size_t i = 0; i < H; i++)
        {
            type q = even[i];
            type r = p * odd[i];
            *(first + i) = q + r;
            *(first + i + H) = q - r;
            p *= g;
        }
        return first;
    }

public:
    static std::vector<type> fft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, true));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        return a;
    }

    static std::vector<type> rfft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, false));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        type iS = Traits::inverse(S);
        for (std::size_t i = 0; i < S; i++)
            a[i] *= iS;
        return a;
    }

    template<typename U>
    static std::vector<type> convolve(const std::vector<U> &a, const std::vector<U> &b)
    {
        assert(!a.empty());
        assert(!b.empty());
        std::size_t S = 1;
        while (S < a.size() + b.size() - 1)
            S *= 2;

        std::vector<type> pa(S), pb(S);
        std::copy(a.begin(), a.end(), pa.begin());
        std::copy(b.begin(), b.end(), pb.begin());
        std::vector<type> A = fft(pa);
        std::vector<type> B = fft(pb);
        for (std::size_t i = 0; i < S; i++)
            A[i] *= B[i];
        pa = rfft(A);
        pa.resize(a.size() + b.size() - 1);
        return pa;
    }
};

template<typename T>
class fft_traits_complex
{
public:
    typedef std::complex<T> type;

    static type inverse(type value)
    {
        return T(1) / value;
    }

    static type generator(std::size_t S, bool invert)
    {
        type g = std::polar(T(1), T(2 * M_PI) / S);
        if (invert)
            g = conj(g);
        return g;
    }
};

typedef FFT<fft_traits_complex<double>> FFTd;

static vi convolve(const vi &a, const vi &b)
{
    auto c1 = FFTd::convolve(a, b);
    vi c(SZ(c1));
    for (int i = 0; i < SZ(c); i++)
    {
        c[i] = ll(round(c1[i].real())) % 1009;
        if (c[i] > 504)
            c[i] -= 1009;
    }
    return c;
}

struct compare_len
{
    bool operator()(const vi &a, const vi &b) const
    {
        return a.size() > b.size();
    }
};

int main(int argc, const char **argv)
{
    redirect(argc, argv);
    int N, M, K;
    cin >> N >> M >> K;
    priority_queue<vi, vector<vi>, compare_len> q;
    vi freq(M);
    for (int i = 0; i < N; i++)
    {
        int x;
        cin >> x;
        freq[x - 1]++;
    }
    for (int x : freq)
    {
        if (x > 0)
            q.push(vi(x + 1, 1));
    }
    while (SZ(q) >= 2)
    {
        vi a = q.top(); q.pop();
        vi b = q.top(); q.pop();
        q.push(convolve(a, b));
    }
    vi c = q.top();
    int ans = (K < SZ(c)) ? c[K] : 0;
    if (ans < 0)
        ans += 1009;
    cout << ans << '\n';

    return 0;
}


//#pragma GCC optimize("O3")
//#pragma GCC target("arch=native,tune=native")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

// Undefined sign for negative inputs
template<typename T>
static T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

// m must be positive
template<typename T>
static T mod(T a, T m)
{
    a %= m;
    if (a < 0)
        a += m;
    return a;
}

// a must be relatively prime to m
template<typename T>
static T inverse(T a, T m)
{
    a = mod(a, m);
    if (a <= 1)
        return a;
    return mod((1 - inverse(m, a) * m) / a, m);
}

template<typename T, typename C, T Modulus>
class MR
{
private:
    struct tag_plus {}; // indicates value is in range [0, 2 * Modulus)
    struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
    struct tag_good {}; // indicates value is in range

    T value;

    static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0, "compute type is too small");
    static_assert(Modulus < std::numeric_limits<T>::max() / 2, "storage type is too small");

    void reduce(tag_plus)
    {
        if (value >= Modulus)
            value -= Modulus;
    }

    void reduce(tag_minus)
    {
        if (value < 0)
            value += Modulus;
    }

    void reduce(tag_good) {}

public:
    typedef T value_type;
    typedef C compute_type;
    static const T modulus = Modulus;

    MR() : value(0) {}
    MR(C value) : value(value % Modulus) { reduce(tag_minus()); }
    template<typename tag_t>
    MR(T value, tag_t tag) : value(value) { reduce(tag); }

    MR &operator=(C value) { this->value = value % Modulus; reduce(tag_minus()); return *this; }

    MR operator +(MR b) const { return MR(value + b.value, tag_plus()); }
    MR operator -(MR b) const { return MR(value - b.value, tag_minus()); }
    MR operator *(MR b) const { return MR(C(value) * C(b.value) % Modulus, tag_good()); }
    MR operator -() const { return MR(-value, tag_minus()); }

    MR &operator +=(MR b) { value += b.value; reduce(tag_plus()); return *this; }
    MR &operator -=(MR b) { value -= b.value; reduce(tag_minus()); return *this; }
    MR &operator *=(MR b) { value = C(value) * C(b.value) % Modulus; return *this; }

    bool operator==(MR b) const { return value == b.value; }
    bool operator!=(MR b) const { return value != b.value; }

    T get() const { return value; }

    // These are only valid if the Modulus is prime, or at least if
    // the dividend is relatively prime to the modulus
    MR inverse() const
    {
        assert(value);
        return MR(::inverse(C(value), C(Modulus)), tag_good());
    }
    MR operator /(MR b) const { return *this * b.inverse(); }
    MR &operator /=(MR b) { return *this *= b.inverse(); }
};

template<typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr)
{
    return o << mr.get();
}

template<typename Traits>
class FFT
{
public:
    typedef typename Traits::type type;

private:
    template<typename It>
    static It fft_r(It first, It last, It tmp_first, It tmp_last, type g)
    {
        std::size_t S = last - first;
        if (S == 1)
            return first;
        else if (S == 2)
        {
            type a = *first;
            type b = *(first + 1);
            *first = a + b;
            *(first + 1) = a - b;
            return first;
        }
        std::size_t H = S / 2;
        It even = tmp_first;
        It odd = tmp_first + H;
        for (std::size_t i = 0; i < H; i++)
        {
            *(even + i) = *(first + 2 * i);
            *(odd + i) = *(first + 2 * i + 1);
        }
        type g2 = g * g;
        even = fft_r(even, odd, first, first + H, g2);
        odd = fft_r(odd, tmp_last, first, first + H, g2);
        if (&*even == &*first)
        {
            swap(first, tmp_first);
            swap(last, tmp_last);
        }
        type p = 1;
        for (std::size_t i = 0; i < H; i++)
        {
            type q = even[i];
            type r = p * odd[i];
            *(first + i) = q + r;
            *(first + i + H) = q - r;
            p *= g;
        }
        return first;
    }

public:
    static std::vector<type> fft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, true));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        return a;
    }

    static std::vector<type> rfft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, false));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        type iS = Traits::inverse(S);
        for (std::size_t i = 0; i < S; i++)
            a[i] *= iS;
        return a;
    }

    template<typename U>
    static std::vector<type> convolve(const std::vector<U> &a, const std::vector<U> &b)
    {
        assert(!a.empty());
        assert(!b.empty());
        std::size_t S = 1;
        while (S < a.size() + b.size() - 1)
            S *= 2;

        std::vector<type> pa(S), pb(S);
        std::copy(a.begin(), a.end(), pa.begin());
        std::copy(b.begin(), b.end(), pb.begin());
        std::vector<type> A = fft(pa);
        std::vector<type> B = fft(pb);
        for (std::size_t i = 0; i < S; i++)
            A[i] *= B[i];
        pa = rfft(A);
        pa.resize(a.size() + b.size() - 1);
        return pa;
    }
};

/* These must satisfy:
 * - len is a power of 2
 * - mod is a prime
 * - len divides mod - 1
 * - gen has order len modulo mod
 */
template<typename T, typename C, T mod, T len, T gen>
class fft_traits_mod
{
public:
    typedef MR<T, C, mod> type;

    static type inverse(type value)
    {
        return value.inverse();
    }

    static type generator(std::size_t S, bool invert)
    {
        assert(len % S == 0);
        type g = gen;
        // compute 2^(len / S)
        T s = S;
        for (; s < len; s <<= 1)
            g *= g;
        if (invert)
            g = g.inverse();
        return g;
    }
};

static const ll P1 = 786433;
static const ll P2 = 1179649;
static const ll P12 = P1 * P2;
typedef FFT<fft_traits_mod<int, ll, 786433, 262144, 5> > FFT2p18;
typedef FFT<fft_traits_mod<int, ll, 1179649, 131072, 74> > FFT2p17;

static ll inv1, inv2;

static vi convolve(const vi &a, const vi &b)
{
    auto c1 = FFT2p18::convolve(a, b);
    auto c2 = FFT2p17::convolve(a, b);
    vi c(SZ(c1));
    for (int i = 0; i < SZ(c); i++)
    {
        ll v = (c1[i].get() * inv2 + c2[i].get() * inv1) % P12;
        c[i] = v % 1009;
    }
    return c;
}

struct compare_len
{
    bool operator()(const vi &a, const vi &b) const
    {
        return a.size() > b.size();
    }
};

int main(int argc, const char **argv)
{
    inv1 = inverse(P1, P2) * P1;
    inv2 = inverse(P2, P1) * P2;

    redirect(argc, argv);
    int N, M, K;
    cin >> N >> M >> K;
    priority_queue<vi, vector<vi>, compare_len> q;
    vi freq(M);
    for (int i = 0; i < N; i++)
    {
        int x;
        cin >> x;
        freq[x - 1]++;
    }
    for (int x : freq)
    {
        if (x > 0)
            q.push(vi(x + 1, 1));
    }
    while (SZ(q) >= 2)
    {
        vi a = q.top(); q.pop();
        vi b = q.top(); q.pop();
        q.push(convolve(a, b));
    }
    vi c = q.top();
    int ans = (K < SZ(c)) ? c[K] : 0;
    cout << ans << '\n';

    return 0;
}


//#pragma GCC optimize("O3")
//#pragma GCC target("arch=native,tune=native")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

// Undefined sign for negative inputs
template<typename T>
static T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

// m must be positive
template<typename T>
static T mod(T a, T m)
{
    a %= m;
    if (a < 0)
        a += m;
    return a;
}

// a must be relatively prime to m
template<typename T>
static T inverse(T a, T m)
{
    a = mod(a, m);
    if (a <= 1)
        return a;
    return mod((1 - inverse(m, a) * m) / a, m);
}

template<typename T, typename C, T Modulus>
class MR
{
private:
    struct tag_plus {}; // indicates value is in range [0, 2 * Modulus)
    struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
    struct tag_good {}; // indicates value is in range

    T value;

    static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0, "compute type is too small");
    static_assert(Modulus < std::numeric_limits<T>::max() / 2, "storage type is too small");

    void reduce(tag_plus)
    {
        if (value >= Modulus)
            value -= Modulus;
    }

    void reduce(tag_minus)
    {
        if (value < 0)
            value += Modulus;
    }

    void reduce(tag_good) {}

public:
    typedef T value_type;
    typedef C compute_type;
    static const T modulus = Modulus;

    MR() : value(0) {}
    MR(C value) : value(value % Modulus) { reduce(tag_minus()); }
    template<typename tag_t>
    MR(T value, tag_t tag) : value(value) { reduce(tag); }

    MR &operator=(C value) { this->value = value % Modulus; reduce(tag_minus()); return *this; }

    MR operator +(MR b) const { return MR(value + b.value, tag_plus()); }
    MR operator -(MR b) const { return MR(value - b.value, tag_minus()); }
    MR operator *(MR b) const { return MR(C(value) * C(b.value) % Modulus, tag_good()); }
    MR operator -() const { return MR(-value, tag_minus()); }

    MR &operator +=(MR b) { value += b.value; reduce(tag_plus()); return *this; }
    MR &operator -=(MR b) { value -= b.value; reduce(tag_minus()); return *this; }
    MR &operator *=(MR b) { value = C(value) * C(b.value) % Modulus; return *this; }

    bool operator==(MR b) const { return value == b.value; }
    bool operator!=(MR b) const { return value != b.value; }

    T get() const { return value; }

    // These are only valid if the Modulus is prime, or at least if
    // the dividend is relatively prime to the modulus
    MR inverse() const
    {
        assert(value);
        return MR(::inverse(C(value), C(Modulus)), tag_good());
    }
    MR operator /(MR b) const { return *this * b.inverse(); }
    MR &operator /=(MR b) { return *this *= b.inverse(); }
};

template<typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr)
{
    return o << mr.get();
}

template<typename Traits>
class FFT
{
public:
    typedef typename Traits::type type;

private:
    template<typename It>
    static It fft_r(It first, It last, It tmp_first, It tmp_last, type g)
    {
        std::size_t S = last - first;
        if (S == 1)
            return first;
        else if (S == 2)
        {
            type a = *first;
            type b = *(first + 1);
            *first = a + b;
            *(first + 1) = a - b;
            return first;
        }
        std::size_t H = S / 2;
        It even = tmp_first;
        It odd = tmp_first + H;
        for (std::size_t i = 0; i < H; i++)
        {
            *(even + i) = *(first + 2 * i);
            *(odd + i) = *(first + 2 * i + 1);
        }
        type g2 = g * g;
        even = fft_r(even, odd, first, first + H, g2);
        odd = fft_r(odd, tmp_last, first, first + H, g2);
        if (&*even == &*first)
        {
            swap(first, tmp_first);
            swap(last, tmp_last);
        }
        type p = 1;
        for (std::size_t i = 0; i < H; i++)
        {
            type q = even[i];
            type r = p * odd[i];
            *(first + i) = q + r;
            *(first + i + H) = q - r;
            p *= g;
        }
        return first;
    }

public:
    static std::vector<type> fft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, true));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        return a;
    }

    static std::vector<type> rfft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, false));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        type iS = Traits::inverse(S);
        for (std::size_t i = 0; i < S; i++)
            a[i] *= iS;
        return a;
    }

    template<typename U>
    static std::vector<type> convolve(const std::vector<U> &a, const std::vector<U> &b)
    {
        assert(!a.empty());
        assert(!b.empty());
        std::size_t S = 1;
        while (S < a.size() + b.size() - 1)
            S *= 2;

        std::vector<type> pa(S), pb(S);
        std::copy(a.begin(), a.end(), pa.begin());
        std::copy(b.begin(), b.end(), pb.begin());
        std::vector<type> A = fft(pa);
        std::vector<type> B = fft(pb);
        for (std::size_t i = 0; i < S; i++)
            A[i] *= B[i];
        pa = rfft(A);
        pa.resize(a.size() + b.size() - 1);
        return pa;
    }
};

template<typename T>
class fft_traits_complex
{
public:
    typedef std::complex<T> type;

    static type inverse(type value)
    {
        return T(1) / value;
    }

    static type generator(std::size_t S, bool invert)
    {
        type g = std::polar(T(1), T(2 * M_PI) / S);
        if (invert)
            g = conj(g);
        return g;
    }
};

typedef FFT<fft_traits_complex<long double>> FFTd;

static vi convolve(const vi &a, const vi &b)
{
    auto c1 = FFTd::convolve(a, b);
    vi c(SZ(c1));
    for (int i = 0; i < SZ(c); i++)
        c[i] = ll(round(c1[i].real())) % 1009;
    return c;
}

struct compare_len
{
    bool operator()(const vi &a, const vi &b) const
    {
        return a.size() > b.size();
    }
};

int main(int argc, const char **argv)
{
    redirect(argc, argv);
    int N, M, K;
    cin >> N >> M >> K;
    priority_queue<vi, vector<vi>, compare_len> q;
    vi freq(M);
    for (int i = 0; i < N; i++)
    {
        int x;
        cin >> x;
        freq[x - 1]++;
    }
    for (int x : freq)
    {
        if (x > 0)
            q.push(vi(x + 1, 1));
    }
    while (SZ(q) >= 2)
    {
        vi a = q.top(); q.pop();
        vi b = q.top(); q.pop();
        q.push(convolve(a, b));
    }
    vi c = q.top();
    int ans = (K < SZ(c)) ? c[K] : 0;
    cout << ans << '\n';

    return 0;
}


//#pragma GCC optimize("O3")
//#pragma GCC target("arch=native,tune=native")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

// Undefined sign for negative inputs
template<typename T> static constexpr T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<typename T> static constexpr T wrap_pos(T a, T m) { return a < 0 ? a + m : a; }
template<typename T> static constexpr T sqr(T a) { return a * a; }
// m must be positive
template<typename T> static constexpr T mod(T a, T m) { return wrap_pos(a % m, m); }

template<typename T>
static constexpr T inverse2(T a, T m)
{
    return a <= 1 ? a : mod((1 - inverse2(m % a, a) * m) / a, m);
}

// a must be relatively prime to m, m > 0
template<typename T>
static constexpr T inverse(T a, T m)
{
    return inverse2(mod(a, m), m);
}

template<typename T, typename P>
static constexpr T power(T a, P b)
{
    return b == 0 ? T(1) : (b % 2) ? power(a, b - 1) * a : sqr(power(a, b / 2));
}

template<typename T, typename C, T Modulus>
class MR
{
private:
    struct tag_plus {}; // indicates value is in range [0, 2 * Modulus)
    struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
    struct tag_good {}; // indicates value is in range

    T value;

    static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0, "compute type is too small");
    static_assert(Modulus < std::numeric_limits<T>::max() / 2, "storage type is too small");

    static constexpr T reduce(T value, tag_plus)
    {
        return value >= Modulus ? value - Modulus : value;
    }

    static constexpr T reduce(T value, tag_minus)
    {
        return value < 0 ? value + Modulus : value;
    }

    static constexpr T reduce(T value, tag_good) { return value; }

public:
    typedef T value_type;
    typedef C compute_type;
    static constexpr T modulus = Modulus;

    constexpr MR() : value(0) {}
    constexpr MR(C value) : value(reduce(value % Modulus, tag_minus())) {}
    template<typename tag_t>
    constexpr MR(T value, tag_t tag) : value(reduce(value, tag)) {}

    MR &operator=(C value) { this->value = reduce(value % Modulus, tag_minus()); return *this; }

    constexpr MR operator +(MR b) const { return MR(value + b.value, tag_plus()); }
    constexpr MR operator -(MR b) const { return MR(value - b.value, tag_minus()); }
    constexpr MR operator *(MR b) const { return MR(C(value) * C(b.value) % Modulus, tag_good()); }
    constexpr MR operator -() const { return MR(-value, tag_minus()); }

    MR &operator +=(MR b) { value = reduce(value + b.value, tag_plus()); return *this; }
    MR &operator -=(MR b) { value = reduce(value - b.value, tag_minus()); return *this; }
    MR &operator *=(MR b) { value = C(value) * C(b.value) % Modulus; return *this; }

    constexpr bool operator==(MR b) const { return value == b.value; }
    constexpr bool operator!=(MR b) const { return value != b.value; }

    constexpr T get() const { return value; }

    // These are only valid if the dividend is relatively prime to the modulus
    constexpr MR inverse() const
    {
        return MR(::inverse(C(value), C(Modulus)), tag_good());
    }
    constexpr MR operator /(MR b) const { return *this * b.inverse(); }
    MR &operator /=(MR b) { return *this *= b.inverse(); }
};

template<typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr)
{
    return o << mr.get();
}

template<typename Traits>
class FFT
{
public:
    typedef typename Traits::type type;

private:
    std::vector<type> roots, rroots;
    std::unique_ptr<FFT> next_plan;
    type inv_size;

    template<typename It>
    It transform(It first, It last, It tmp_first, It tmp_last, bool invert) const
    {
        const std::vector<type> &rr = invert ? rroots : roots;
        std::size_t S = size();
        if (S == 1)
            return first;
        else if (S == 2)
        {
            type a = *first;
            type b = *(first + 1);
            *first = a + b;
            *(first + 1) = a - b;
            return first;
        }
        std::size_t H = S / 2;
        It even = tmp_first;
        It odd = tmp_first + H;
        for (std::size_t i = 0; i < H; i++)
        {
            *(even + i) = *(first + 2 * i);
            *(odd + i) = *(first + (2 * i + 1));
        }
        even = next_plan->transform(even, odd, first, first + H, invert);
        odd = next_plan->transform(odd, tmp_last, first, first + H, invert);
        if (&*even == &*first)
        {
            swap(first, tmp_first);
            swap(last, tmp_last);
        }
        for (std::size_t i = 0; i < H; i++)
        {
            type q = even[i];
            type r = rr[i] * odd[i];
            *(first + i) = q + r;
            *(first + i + H) = q - r;
        }
        return first;
    }

    void transform(std::vector<type> &a, bool invert) const
    {
        assert(a.size() == size());
        std::vector<type> tmp(a.size());
        auto pos = transform(a.begin(), a.end(), tmp.begin(), tmp.end(), invert);
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
    }

public:
    std::size_t size() const { return roots.size(); }

    FFT(std::size_t len)
    {
        if (len > 1)
        {
            assert(len % 2 == 0);
            next_plan.reset(new FFT(len / 2));
            roots.reserve(len);
            type g = Traits::generator(len);
            for (const type &r : next_plan->roots)
            {
                roots.push_back(r);
                roots.push_back(g * r);
            }
            rroots.reserve(len);
            rroots.push_back(roots[0]);
            rroots.insert(rroots.end(), roots.rbegin(), roots.rend() - 1);
        }
        else
        {
            roots.push_back(1);
            rroots.push_back(1);
        }
        inv_size = Traits::inverse(len);
    }

    template<typename U>
    std::vector<type> convolve(const std::vector<U> &a, const std::vector<U> &b) const
    {
        assert(!a.empty());
        assert(!b.empty());
        assert(a.size() + b.size() - 1 <= size());

        std::vector<type> pa(size()), pb(size());
        std::copy(a.begin(), a.end(), pa.begin());
        std::copy(b.begin(), b.end(), pb.begin());
        transform(pa, false);
        transform(pb, false);
        for (std::size_t i = 0; i < size(); i++)
            pa[i] *= pb[i];
        transform(pa, true);
        pa.resize(a.size() + b.size() - 1);
        for (type &v : pa)
            v *= inv_size;
        return pa;
    }
};

template<typename Plan, typename U>
static std::vector<typename Plan::type>
convolve(const std::vector<U> &a, const std::vector<U> &b)
{
    std::size_t S = 1;
    while (S < a.size() + b.size() - 1)
        S *= 2;
    Plan plan(S);
    return plan.convolve(a, b);
}

template<typename T>
static constexpr T find_gen(typename T::value_type len, T start = 2)
{
    return power(start, len / 2) == -1 ? start : find_gen<T>(len, start + 1);
}

/* These must satisfy:
 * - len is a power of 2
 * - mod is a prime
 * - len divides mod - 1
 */
template<typename T, typename C, T mod, T len>
class fft_traits_mod
{
public:
    typedef MR<T, C, mod> type;

    static type inverse(type value)
    {
        return value.inverse();
    }

    static type generator(std::size_t S)
    {
        static constexpr type gen = find_gen<type>(len);
        assert(len % S == 0);
        type g = gen;
        // compute 2^(len / S)
        T s = S;
        for (; s < len; s <<= 1)
            g *= g;
        return g;
    }
};

static constexpr ll P1 = 786433;
static constexpr ll P2 = 5767169;
static constexpr ll P12 = P1 * P2;
static constexpr ll inv1 = inverse(P1, P2) * P1;
static constexpr ll inv2 = inverse(P2, P1) * P2;
typedef FFT<fft_traits_mod<int, ll, P1, 262144> > FFT1;
typedef FFT<fft_traits_mod<int, ll, P2, 262144> > FFT2;

static vi convolve1(const vi &a, const vi &b)
{
    auto c1 = convolve<FFT1>(a, b);
    auto c2 = convolve<FFT2>(a, b);
    vi c(SZ(c1));
    for (int i = 0; i < SZ(c); i++)
    {
        ll v = (c1[i].get() * inv2 + c2[i].get() * inv1) % P12;
        c[i] = v % 1009;
    }
    return c;
}

struct compare_len
{
    bool operator()(const vi &a, const vi &b) const
    {
        return a.size() > b.size();
    }
};

int main(int argc, const char **argv)
{
    redirect(argc, argv);
    int N, M, K;
    cin >> N >> M >> K;
    priority_queue<vi, vector<vi>, compare_len> q;
    vi freq(M);
    for (int i = 0; i < N; i++)
    {
        int x;
        cin >> x;
        freq[x - 1]++;
    }
    for (int x : freq)
    {
        if (x > 0)
            q.push(vi(x + 1, 1));
    }
    while (SZ(q) >= 2)
    {
        vi a = q.top(); q.pop();
        vi b = q.top(); q.pop();
        q.push(convolve1(a, b));
    }
    vi c = q.top();
    int ans = (K < SZ(c)) ? c[K] : 0;
    if (ans < 0)
        ans += 1009;
    cout << ans << '\n';

    return 0;
}


//#pragma GCC optimize("O3")
//#pragma GCC target("arch=native,tune=native")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

// Undefined sign for negative inputs
template<typename T>
static T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

// m must be positive
template<typename T>
static T mod(T a, T m)
{
    a %= m;
    if (a < 0)
        a += m;
    return a;
}

// a must be relatively prime to m
template<typename T>
static T inverse(T a, T m)
{
    a = mod(a, m);
    if (a <= 1)
        return a;
    return mod((1 - inverse(m, a) * m) / a, m);
}

template<typename T, typename C, T Modulus>
class MR
{
private:
    struct tag_plus {}; // indicates value is in range [0, 2 * Modulus)
    struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
    struct tag_good {}; // indicates value is in range

    T value;

    static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0, "compute type is too small");
    static_assert(Modulus < std::numeric_limits<T>::max() / 2, "storage type is too small");

    void reduce(tag_plus)
    {
        if (value >= Modulus)
            value -= Modulus;
    }

    void reduce(tag_minus)
    {
        if (value < 0)
            value += Modulus;
    }

    void reduce(tag_good) {}

public:
    typedef T value_type;
    typedef C compute_type;
    static const T modulus = Modulus;

    MR() : value(0) {}
    MR(C value) : value(value % Modulus) { reduce(tag_minus()); }
    template<typename tag_t>
    MR(T value, tag_t tag) : value(value) { reduce(tag); }

    MR &operator=(C value) { this->value = value % Modulus; reduce(tag_minus()); return *this; }

    MR operator +(MR b) const { return MR(value + b.value, tag_plus()); }
    MR operator -(MR b) const { return MR(value - b.value, tag_minus()); }
    MR operator *(MR b) const { return MR(C(value) * C(b.value) % Modulus, tag_good()); }
    MR operator -() const { return MR(-value, tag_minus()); }

    MR &operator +=(MR b) { value += b.value; reduce(tag_plus()); return *this; }
    MR &operator -=(MR b) { value -= b.value; reduce(tag_minus()); return *this; }
    MR &operator *=(MR b) { value = C(value) * C(b.value) % Modulus; return *this; }

    bool operator==(MR b) const { return value == b.value; }
    bool operator!=(MR b) const { return value != b.value; }

    T get() const { return value; }

    // These are only valid if the Modulus is prime, or at least if
    // the dividend is relatively prime to the modulus
    MR inverse() const
    {
        assert(value);
        return MR(::inverse(C(value), C(Modulus)), tag_good());
    }
    MR operator /(MR b) const { return *this * b.inverse(); }
    MR &operator /=(MR b) { return *this *= b.inverse(); }
};

template<typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr)
{
    return o << mr.get();
}

template<typename Traits>
class FFT
{
public:
    typedef typename Traits::type type;

private:
    template<typename It>
    static It fft_r(It first, It last, It tmp_first, It tmp_last, type g)
    {
        std::size_t S = last - first;
        if (S == 1)
            return first;
        else if (S == 2)
        {
            type a = *first;
            type b = *(first + 1);
            *first = a + b;
            *(first + 1) = a - b;
            return first;
        }
        std::size_t H = S / 2;
        It even = tmp_first;
        It odd = tmp_first + H;
        for (std::size_t i = 0; i < H; i++)
        {
            *(even + i) = *(first + 2 * i);
            *(odd + i) = *(first + 2 * i + 1);
        }
        type g2 = g * g;
        even = fft_r(even, odd, first, first + H, g2);
        odd = fft_r(odd, tmp_last, first, first + H, g2);
        if (&*even == &*first)
        {
            swap(first, tmp_first);
            swap(last, tmp_last);
        }
        type p = 1;
        for (std::size_t i = 0; i < H; i++)
        {
            type q = even[i];
            type r = p * odd[i];
            *(first + i) = q + r;
            *(first + i + H) = q - r;
            p *= g;
        }
        return first;
    }

public:
    static std::vector<type> fft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, true));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        return a;
    }

    static std::vector<type> rfft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, false));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        type iS = Traits::inverse(S);
        for (std::size_t i = 0; i < S; i++)
            a[i] *= iS;
        return a;
    }

    template<typename U>
    static std::vector<type> convolve(const std::vector<U> &a, const std::vector<U> &b)
    {
        assert(!a.empty());
        assert(!b.empty());
        std::size_t S = 1;
        while (S < a.size() + b.size() - 1)
            S *= 2;

        std::vector<type> pa(S), pb(S);
        std::copy(a.begin(), a.end(), pa.begin());
        std::copy(b.begin(), b.end(), pb.begin());
        std::vector<type> A = fft(pa);
        std::vector<type> B = fft(pb);
        for (std::size_t i = 0; i < S; i++)
            A[i] *= B[i];
        pa = rfft(A);
        pa.resize(a.size() + b.size() - 1);
        return pa;
    }
};

template<typename T>
class fft_traits_complex
{
public:
    typedef std::complex<T> type;

    static type inverse(type value)
    {
        return 1.0 / value;
    }

    static type generator(std::size_t S, bool invert)
    {
        type g = std::polar(1.0, 2 * M_PI / S);
        if (invert)
            g = conj(g);
        return g;
    }
};

typedef FFT<fft_traits_complex<long double>> FFTd;

static vi convolve(const vi &a, const vi &b)
{
    auto c1 = FFTd::convolve(a, b);
    vi c(SZ(c1));
    for (int i = 0; i < SZ(c); i++)
        c[i] = ll(round(c1[i].real())) % 1009;
    return c;
}

struct compare_len
{
    bool operator()(const vi &a, const vi &b) const
    {
        return a.size() > b.size();
    }
};

int main(int argc, const char **argv)
{
    redirect(argc, argv);
    int N, M, K;
    cin >> N >> M >> K;
    priority_queue<vi, vector<vi>, compare_len> q;
    vi freq(M);
    for (int i = 0; i < N; i++)
    {
        int x;
        cin >> x;
        freq[x - 1]++;
    }
    for (int x : freq)
    {
        if (x > 0)
            q.push(vi(x + 1, 1));
    }
    while (SZ(q) >= 2)
    {
        vi a = q.top(); q.pop();
        vi b = q.top(); q.pop();
        q.push(convolve(a, b));
    }
    vi c = q.top();
    int ans = (K < SZ(c)) ? c[K] : 0;
    cout << ans << '\n';

    return 0;
}


//#pragma GCC optimize("O3")
//#pragma GCC target("arch=native,tune=native")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

template<typename Traits>
class FFT
{
public:
    typedef typename Traits::type type;

private:
    std::vector<type> roots, rroots;
    std::unique_ptr<FFT> next_plan;
    type inv_size;

    template<typename It>
    It transform(It first, It last, It tmp_first, It tmp_last, bool invert) const
    {
        const std::vector<type> &rr = invert ? rroots : roots;
        std::size_t S = size();
        if (S == 1)
            return first;
        else if (S == 2)
        {
            type a = *first;
            type b = *(first + 1);
            *first = a + b;
            *(first + 1) = a - b;
            return first;
        }
        std::size_t H = S / 2;
        It even = tmp_first;
        It odd = tmp_first + H;
        for (std::size_t i = 0; i < H; i++)
        {
            *(even + i) = *(first + 2 * i);
            *(odd + i) = *(first + (2 * i + 1));
        }
        even = next_plan->transform(even, odd, first, first + H, invert);
        odd = next_plan->transform(odd, tmp_last, first, first + H, invert);
        if (&*even == &*first)
        {
            swap(first, tmp_first);
            swap(last, tmp_last);
        }
        for (std::size_t i = 0; i < H; i++)
        {
            type q = even[i];
            type r = rr[i] * odd[i];
            *(first + i) = q + r;
            *(first + i + H) = q - r;
        }
        return first;
    }

    void transform(std::vector<type> &a, bool invert) const
    {
        assert(a.size() == size());
        std::vector<type> tmp(a.size());
        auto pos = transform(a.begin(), a.end(), tmp.begin(), tmp.end(), invert);
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
    }

public:
    std::size_t size() const { return roots.size(); }

    FFT(std::size_t len)
    {
        if (len > 1)
        {
            assert(len % 2 == 0);
            next_plan.reset(new FFT(len / 2));
            roots.reserve(len);
            type g = Traits::generator(len);
            for (const type &r : next_plan->roots)
            {
                roots.push_back(r);
                roots.push_back(g * r);
            }
            rroots.reserve(len);
            rroots.push_back(roots[0]);
            rroots.insert(rroots.end(), roots.rbegin(), roots.rend() - 1);
        }
        else
        {
            roots.push_back(1);
            rroots.push_back(1);
        }
        inv_size = Traits::inverse(len);
    }

    template<typename U>
    std::vector<type> convolve(const std::vector<U> &a, const std::vector<U> &b) const
    {
        assert(!a.empty());
        assert(!b.empty());
        assert(a.size() + b.size() - 1 <= size());

        std::vector<type> pa(size()), pb(size());
        std::copy(a.begin(), a.end(), pa.begin());
        std::copy(b.begin(), b.end(), pb.begin());
        transform(pa, false);
        transform(pb, false);
        for (std::size_t i = 0; i < size(); i++)
            pa[i] *= pb[i];
        transform(pa, true);
        pa.resize(a.size() + b.size() - 1);
        for (type &v : pa)
            v *= inv_size;
        return pa;
    }
};

template<typename Plan, typename U>
static std::vector<typename Plan::type>
convolve(const std::vector<U> &a, const std::vector<U> &b)
{
    std::size_t S = 1;
    while (S < a.size() + b.size() - 1)
        S *= 2;
    Plan plan(S);
    return plan.convolve(a, b);
}

template<typename T>
class fft_traits_complex
{
public:
    typedef std::complex<T> type;

    static type inverse(type value)
    {
        return T(1) / value;
    }

    static type generator(std::size_t S)
    {
        type g = std::polar(T(1), T(-2 * M_PI) / S);
        return g;
    }
};

typedef FFT<fft_traits_complex<double>> FFTd;

static vi convolve1(const vi &a, const vi &b)
{
    auto c1 = convolve<FFTd>(a, b);
    vi c(SZ(c1));
    for (int i = 0; i < SZ(c); i++)
    {
        c[i] = ll(round(c1[i].real())) % 1009;
        if (c[i] > 504)
            c[i] -= 1009;
    }
    return c;
}

struct compare_len
{
    bool operator()(const vi &a, const vi &b) const
    {
        return a.size() > b.size();
    }
};

int main(int argc, const char **argv)
{
    redirect(argc, argv);
    int N, M, K;
    cin >> N >> M >> K;
    priority_queue<vi, vector<vi>, compare_len> q;
    vi freq(M);
    for (int i = 0; i < N; i++)
    {
        int x;
        cin >> x;
        freq[x - 1]++;
    }
    for (int x : freq)
    {
        if (x > 0)
            q.push(vi(x + 1, 1));
    }
    while (SZ(q) >= 2)
    {
        vi a = q.top(); q.pop();
        vi b = q.top(); q.pop();
        q.push(convolve1(a, b));
    }
    vi c = q.top();
    int ans = (K < SZ(c)) ? c[K] : 0;
    if (ans < 0)
        ans += 1009;
    cout << ans << '\n';

    return 0;
}


//#pragma GCC optimize("O3")
//#pragma GCC target("arch=native,tune=native")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

// Undefined sign for negative inputs
template<typename T>
static T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

// m must be positive
template<typename T>
static T mod(T a, T m)
{
    a %= m;
    if (a < 0)
        a += m;
    return a;
}

// a must be relatively prime to m
template<typename T>
static T inverse(T a, T m)
{
    a = mod(a, m);
    if (a <= 1)
        return a;
    return mod((1 - inverse(m, a) * m) / a, m);
}

template<typename T, typename C, T Modulus>
class MR
{
private:
    struct tag_plus {}; // indicates value is in range [0, 2 * Modulus)
    struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
    struct tag_good {}; // indicates value is in range

    T value;

    static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0, "compute type is too small");
    static_assert(Modulus < std::numeric_limits<T>::max() / 2, "storage type is too small");

    void reduce(tag_plus)
    {
        if (value >= Modulus)
            value -= Modulus;
    }

    void reduce(tag_minus)
    {
        if (value < 0)
            value += Modulus;
    }

    void reduce(tag_good) {}

public:
    typedef T value_type;
    typedef C compute_type;
    static const T modulus = Modulus;

    MR() : value(0) {}
    MR(C value) : value(value % Modulus) { reduce(tag_minus()); }
    template<typename tag_t>
    MR(T value, tag_t tag) : value(value) { reduce(tag); }

    MR &operator=(C value) { this->value = value % Modulus; reduce(tag_minus()); return *this; }

    MR operator +(MR b) const { return MR(value + b.value, tag_plus()); }
    MR operator -(MR b) const { return MR(value - b.value, tag_minus()); }
    MR operator *(MR b) const { return MR(C(value) * C(b.value) % Modulus, tag_good()); }
    MR operator -() const { return MR(-value, tag_minus()); }

    MR &operator +=(MR b) { value += b.value; reduce(tag_plus()); return *this; }
    MR &operator -=(MR b) { value -= b.value; reduce(tag_minus()); return *this; }
    MR &operator *=(MR b) { value = C(value) * C(b.value) % Modulus; return *this; }

    bool operator==(MR b) const { return value == b.value; }
    bool operator!=(MR b) const { return value != b.value; }

    T get() const { return value; }

    // These are only valid if the Modulus is prime, or at least if
    // the dividend is relatively prime to the modulus
    MR inverse() const
    {
        assert(value);
        return MR(::inverse(C(value), C(Modulus)), tag_good());
    }
    MR operator /(MR b) const { return *this * b.inverse(); }
    MR &operator /=(MR b) { return *this *= b.inverse(); }
};

template<typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr)
{
    return o << mr.get();
}

template<typename Traits>
class FFT
{
public:
    typedef typename Traits::type type;

private:
    template<typename It>
    static It fft_r(It first, It last, It tmp_first, It tmp_last, type g)
    {
        std::size_t S = last - first;
        if (S == 1)
            return first;
        else if (S == 2)
        {
            type a = *first;
            type b = *(first + 1);
            *first = a + b;
            *(first + 1) = a - b;
            return first;
        }
        std::size_t H = S / 2;
        It even = tmp_first;
        It odd = tmp_first + H;
        for (std::size_t i = 0; i < H; i++)
        {
            *(even + i) = *(first + 2 * i);
            *(odd + i) = *(first + 2 * i + 1);
        }
        type g2 = g * g;
        even = fft_r(even, odd, first, first + H, g2);
        odd = fft_r(odd, tmp_last, first, first + H, g2);
        if (&*even == &*first)
        {
            swap(first, tmp_first);
            swap(last, tmp_last);
        }
        type p = 1;
        for (std::size_t i = 0; i < H; i++)
        {
            type q = even[i];
            type r = p * odd[i];
            *(first + i) = q + r;
            *(first + i + H) = q - r;
            p *= g;
        }
        return first;
    }

public:
    static std::vector<type> fft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, true));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        return a;
    }

    static std::vector<type> rfft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, false));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        type iS = Traits::inverse(S);
        for (std::size_t i = 0; i < S; i++)
            a[i] *= iS;
        return a;
    }

    template<typename U>
    static std::vector<type> convolve(const std::vector<U> &a, const std::vector<U> &b)
    {
        assert(!a.empty());
        assert(!b.empty());
        std::size_t S = 1;
        while (S < a.size() + b.size() - 1)
            S *= 2;

        std::vector<type> pa(S), pb(S);
        std::copy(a.begin(), a.end(), pa.begin());
        std::copy(b.begin(), b.end(), pb.begin());
        std::vector<type> A = fft(pa);
        std::vector<type> B = fft(pb);
        for (std::size_t i = 0; i < S; i++)
            A[i] *= B[i];
        pa = rfft(A);
        pa.resize(a.size() + b.size() - 1);
        return pa;
    }
};

template<typename T>
class fft_traits_complex
{
public:
    typedef std::complex<T> type;

    static type inverse(type value)
    {
        return T(1) / value;
    }

    static type generator(std::size_t S, bool invert)
    {
        type g = std::polar(T(1), T(2 * M_PI) / S);
        if (invert)
            g = conj(g);
        return g;
    }
};

typedef FFT<fft_traits_complex<double>> FFTd;

static vi convolve(const vi &a, const vi &b)
{
    auto c1 = FFTd::convolve(a, b);
    vi c(SZ(c1));
    for (int i = 0; i < SZ(c); i++)
    {
        c[i] = ll(round(c1[i].real())) % 1009;
        if (c[i] > 504)
            c[i] -= 1009;
    }
    return c;
}

struct compare_len
{
    bool operator()(const vi &a, const vi &b) const
    {
        return a.size() > b.size();
    }
};

int main(int argc, const char **argv)
{
    redirect(argc, argv);
    int N, M, K;
    cin >> N >> M >> K;
    priority_queue<vi, vector<vi>, compare_len> q;
    vi freq(M);
    for (int i = 0; i < N; i++)
    {
        int x;
        cin >> x;
        freq[x - 1]++;
    }
    for (int x : freq)
    {
        if (x > 0)
            q.push(vi(x + 1, 1));
    }
    while (SZ(q) >= 2)
    {
        vi a = q.top(); q.pop();
        vi b = q.top(); q.pop();
        q.push(convolve(a, b));
    }
    vi c = q.top();
    int ans = (K < SZ(c)) ? c[K] : 0;
    if (ans < 0)
        ans += 1009;
    cout << ans << '\n';

    return 0;
}


//#pragma GCC optimize("O3")
//#pragma GCC target("arch=native,tune=native")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

// Undefined sign for negative inputs
template<typename T> static constexpr T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }
template<typename T> static constexpr T wrap_pos(T a, T m) { return a < 0 ? a + m : a; }
template<typename T> static constexpr T sqr(T a) { return a * a; }
// m must be positive
template<typename T> static constexpr T mod(T a, T m) { return wrap_pos(a % m, m); }

template<typename T>
static constexpr T inverse2(T a, T m)
{
    return a <= 1 ? a : mod((1 - inverse2(m % a, a) * m) / a, m);
}

// a must be relatively prime to m, m > 0
template<typename T>
static constexpr T inverse(T a, T m)
{
    return inverse2(mod(a, m), m);
}

template<typename T, typename P>
static constexpr T power(T a, P b)
{
    return b == 0 ? T(1) : (b % 2) ? power(a, b - 1) * a : sqr(power(a, b / 2));
}

template<typename T, typename C, T Modulus>
class MR
{
private:
    struct tag_plus {}; // indicates value is in range [0, 2 * Modulus)
    struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
    struct tag_good {}; // indicates value is in range

    T value;

    static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0, "compute type is too small");
    static_assert(Modulus < std::numeric_limits<T>::max() / 2, "storage type is too small");

    static constexpr T reduce(T value, tag_plus)
    {
        return value >= Modulus ? value - Modulus : value;
    }

    static constexpr T reduce(T value, tag_minus)
    {
        return value < 0 ? value + Modulus : value;
    }

    static constexpr T reduce(T value, tag_good) { return value; }

public:
    typedef T value_type;
    typedef C compute_type;
    static constexpr T modulus = Modulus;

    constexpr MR() : value(0) {}
    constexpr MR(C value) : value(reduce(value % Modulus, tag_minus())) {}
    template<typename tag_t>
    constexpr MR(T value, tag_t tag) : value(reduce(value, tag)) {}

    MR &operator=(C value) { this->value = reduce(value % Modulus, tag_minus()); return *this; }

    constexpr MR operator +(MR b) const { return MR(value + b.value, tag_plus()); }
    constexpr MR operator -(MR b) const { return MR(value - b.value, tag_minus()); }
    constexpr MR operator *(MR b) const { return MR(C(value) * C(b.value) % Modulus, tag_good()); }
    constexpr MR operator -() const { return MR(-value, tag_minus()); }

    MR &operator +=(MR b) { value = reduce(value + b.value, tag_plus()); return *this; }
    MR &operator -=(MR b) { value = reduce(value - b.value, tag_minus()); return *this; }
    MR &operator *=(MR b) { value = C(value) * C(b.value) % Modulus; return *this; }

    constexpr bool operator==(MR b) const { return value == b.value; }
    constexpr bool operator!=(MR b) const { return value != b.value; }

    constexpr T get() const { return value; }

    // These are only valid if the dividend is relatively prime to the modulus
    constexpr MR inverse() const
    {
        return MR(::inverse(C(value), C(Modulus)), tag_good());
    }
    constexpr MR operator /(MR b) const { return *this * b.inverse(); }
    MR &operator /=(MR b) { return *this *= b.inverse(); }
};

template<typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr)
{
    return o << mr.get();
}

template<typename Traits>
class FFT
{
public:
    typedef typename Traits::type type;

private:
    std::vector<type> roots, rroots;
    std::unique_ptr<FFT> next_plan;
    type inv_size;

    template<typename It>
    It transform(It first, It last, It tmp_first, It tmp_last, bool invert) const
    {
        const std::vector<type> &rr = invert ? rroots : roots;
        std::size_t S = size();
        if (S == 1)
            return first;
        else if (S == 2)
        {
            type a = *first;
            type b = *(first + 1);
            *first = a + b;
            *(first + 1) = a - b;
            return first;
        }
        std::size_t H = S / 2;
        It even = tmp_first;
        It odd = tmp_first + H;
        for (std::size_t i = 0; i < H; i++)
        {
            *(even + i) = *(first + 2 * i);
            *(odd + i) = *(first + (2 * i + 1));
        }
        even = next_plan->transform(even, odd, first, first + H, invert);
        odd = next_plan->transform(odd, tmp_last, first, first + H, invert);
        if (&*even == &*first)
        {
            swap(first, tmp_first);
            swap(last, tmp_last);
        }
        for (std::size_t i = 0; i < H; i++)
        {
            type q = even[i];
            type r = rr[i] * odd[i];
            *(first + i) = q + r;
            *(first + i + H) = q - r;
        }
        return first;
    }

    void transform(std::vector<type> &a, bool invert) const
    {
        assert(a.size() == size());
        std::vector<type> tmp(a.size());
        auto pos = transform(a.begin(), a.end(), tmp.begin(), tmp.end(), invert);
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
    }

public:
    std::size_t size() const { return roots.size(); }

    FFT(std::size_t len)
    {
        if (len > 1)
        {
            assert(len % 2 == 0);
            next_plan.reset(new FFT(len / 2));
            roots.reserve(len);
            type g = Traits::generator(len);
            for (const type &r : next_plan->roots)
            {
                roots.push_back(r);
                roots.push_back(g * r);
            }
            rroots.reserve(len);
            rroots.push_back(roots[0]);
            rroots.insert(rroots.end(), roots.rbegin(), roots.rend() - 1);
        }
        else
        {
            roots.push_back(1);
            rroots.push_back(1);
        }
        inv_size = Traits::inverse(len);
    }

    template<typename U>
    std::vector<type> convolve(const std::vector<U> &a, const std::vector<U> &b) const
    {
        assert(!a.empty());
        assert(!b.empty());
        assert(a.size() + b.size() - 1 <= size());

        std::vector<type> pa(size()), pb(size());
        std::copy(a.begin(), a.end(), pa.begin());
        std::copy(b.begin(), b.end(), pb.begin());
        transform(pa, false);
        transform(pb, false);
        for (std::size_t i = 0; i < size(); i++)
            pa[i] *= pb[i];
        transform(pa, true);
        pa.resize(a.size() + b.size() - 1);
        for (type &v : pa)
            v *= inv_size;
        return pa;
    }
};

template<typename Plan, typename U>
static std::vector<typename Plan::type>
convolve(const std::vector<U> &a, const std::vector<U> &b)
{
    std::size_t S = 1;
    while (S < a.size() + b.size() - 1)
        S *= 2;
    Plan plan(S);
    return plan.convolve(a, b);
}

template<typename T>
static constexpr T find_gen(typename T::value_type len, T start = 2)
{
    return power(start, len / 2) == -1 ? start : find_gen<T>(len, start + 1);
}

/* These must satisfy:
 * - len is a power of 2
 * - mod is a prime
 * - len divides mod - 1
 */
template<typename T, typename C, T mod, T len>
class fft_traits_mod
{
public:
    typedef MR<T, C, mod> type;

    static type inverse(type value)
    {
        return value.inverse();
    }

    static type generator(std::size_t S)
    {
        static constexpr type gen = find_gen<type>(len);
        assert(len % S == 0);
        type g = gen;
        // compute 2^(len / S)
        T s = S;
        for (; s < len; s <<= 1)
            g *= g;
        return g;
    }
};

static constexpr ll P1 = 786433;
static constexpr ll P2 = 5767169;
static constexpr ll P12 = P1 * P2;
static constexpr ll inv1 = inverse(P1, P2) * P1;
static constexpr ll inv2 = inverse(P2, P1) * P2;
typedef FFT<fft_traits_mod<int, ll, P1, 262144> > FFT1;
typedef FFT<fft_traits_mod<int, ll, P2, 262144> > FFT2;

static vector<pair<FFT1, FFT2>> plans;

static vi convolve1(const vi &a, const vi &b)
{
    size_t S = a.size() + b.size() - 1;
    int p = 0;
    while (plans[p].first.size() < S)
        p++;
    auto c1 = plans[p].first.convolve(a, b);
    auto c2 = plans[p].second.convolve(a, b);
    vi c(SZ(c1));
    for (int i = 0; i < SZ(c); i++)
    {
        ll v = (c1[i].get() * inv2 + c2[i].get() * inv1) % P12;
        c[i] = v % 1009;
    }
    return c;
}

struct compare_len
{
    bool operator()(const vi &a, const vi &b) const
    {
        return a.size() > b.size();
    }
};

int main(int argc, const char **argv)
{
    redirect(argc, argv);
    int N, M, K;
    cin >> N >> M >> K;
    priority_queue<vi, vector<vi>, compare_len> q;
    vi freq(M);
    for (int i = 0; i < N; i++)
    {
        int x;
        cin >> x;
        freq[x - 1]++;
    }
    for (int x : freq)
    {
        if (x > 0)
            q.push(vi(x + 1, 1));
    }

    for (int i = 1; i <= 2 * N; i *= 2)
    {
        plans.push_back(make_pair(FFT1(i), FFT2(i)));
    }

    while (SZ(q) >= 2)
    {
        vi a = q.top(); q.pop();
        vi b = q.top(); q.pop();
        q.push(convolve1(a, b));
    }
    vi c = q.top();
    int ans = (K < SZ(c)) ? c[K] : 0;
    if (ans < 0)
        ans += 1009;
    cout << ans << '\n';

    return 0;
}


//#pragma GCC optimize("O3")
//#pragma GCC target("arch=native,tune=native")
#include <bits/stdc++.h>
#ifndef ONLINE_JUDGE
# include <sys/time.h>
# include <sys/resource.h>
#endif

/*** TEMPLATE CODE STARTS HERE ***/

#ifndef M_PI
#define M_PI 3.1415926535897932384626433832795028841971693993751
#endif

using namespace std;

typedef vector<string> vs;
typedef long long ll;
typedef complex<double> pnt;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;

#define RA(x) begin(x), end(x)
#define FE(i, x) for (auto i = begin(x); i != end(x); ++i)
#define SZ(x) ((ll) (x).size())

template<class T>
void splitstr(const string &s, vector<T> &out)
{
    istringstream in(s);
    out.clear();
    copy(istream_iterator<T>(in), istream_iterator<T>(), back_inserter(out));
}

static void redirect(int argc, const char **argv)
{
#ifndef ONLINE_JUDGE
    struct rlimit rlim;
    getrlimit(RLIMIT_STACK, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_STACK, &rlim);
#ifndef __SANITIZE_ADDRESS__
    getrlimit(RLIMIT_DATA, &rlim);
    rlim.rlim_cur = 256 * 1024 * 1024;
    setrlimit(RLIMIT_DATA, &rlim);
#endif
#endif

    ios::sync_with_stdio(false);
    cin.tie(NULL);
    if (argc > 1)
    {
        static filebuf f;
        f.open(argv[1], ios::in);
        cin.rdbuf(&f);
        if (!cin)
        {
            cerr << "Failed to open '" << argv[1] << "'" << endl;
            exit(1);
        }
    }

    if (argc > 2)
    {
        static filebuf f;
        f.open(argv[2], ios::out | ios::trunc);
        cout.rdbuf(&f);
        if (!cout)
        {
            cerr << "Failed to open '" << argv[2] << "'" << endl;
        }
    }
}

/*** TEMPLATE CODE ENDS HERE */

// Undefined sign for negative inputs
template<typename T>
static T gcd(T a, T b) { return b ? gcd(b, a % b) : a; }

// m must be positive
template<typename T>
static T mod(T a, T m)
{
    a %= m;
    if (a < 0)
        a += m;
    return a;
}

// a must be relatively prime to m
template<typename T>
static T inverse(T a, T m)
{
    a = mod(a, m);
    if (a <= 1)
        return a;
    return mod((1 - inverse(m, a) * m) / a, m);
}

template<typename T, typename C, T Modulus>
class MR
{
private:
    struct tag_plus {}; // indicates value is in range [0, 2 * Modulus)
    struct tag_minus {}; // indicates value is in range (-Modulus, Modulus)
    struct tag_good {}; // indicates value is in range

    T value;

    static_assert(std::numeric_limits<C>::max() / Modulus / Modulus > 0, "compute type is too small");
    static_assert(Modulus < std::numeric_limits<T>::max() / 2, "storage type is too small");

    void reduce(tag_plus)
    {
        if (value >= Modulus)
            value -= Modulus;
    }

    void reduce(tag_minus)
    {
        if (value < 0)
            value += Modulus;
    }

    void reduce(tag_good) {}

public:
    typedef T value_type;
    typedef C compute_type;
    static const T modulus = Modulus;

    MR() : value(0) {}
    MR(C value) : value(value % Modulus) { reduce(tag_minus()); }
    template<typename tag_t>
    MR(T value, tag_t tag) : value(value) { reduce(tag); }

    MR &operator=(C value) { this->value = value % Modulus; reduce(tag_minus()); return *this; }

    MR operator +(MR b) const { return MR(value + b.value, tag_plus()); }
    MR operator -(MR b) const { return MR(value - b.value, tag_minus()); }
    MR operator *(MR b) const { return MR(C(value) * C(b.value) % Modulus, tag_good()); }
    MR operator -() const { return MR(-value, tag_minus()); }

    MR &operator +=(MR b) { value += b.value; reduce(tag_plus()); return *this; }
    MR &operator -=(MR b) { value -= b.value; reduce(tag_minus()); return *this; }
    MR &operator *=(MR b) { value = C(value) * C(b.value) % Modulus; return *this; }

    bool operator==(MR b) const { return value == b.value; }
    bool operator!=(MR b) const { return value != b.value; }

    T get() const { return value; }

    // These are only valid if the Modulus is prime, or at least if
    // the dividend is relatively prime to the modulus
    MR inverse() const
    {
        assert(value);
        return MR(::inverse(C(value), C(Modulus)), tag_good());
    }
    MR operator /(MR b) const { return *this * b.inverse(); }
    MR &operator /=(MR b) { return *this *= b.inverse(); }
};

template<typename T, typename C, T Modulus>
static inline std::ostream &operator<<(std::ostream &o, MR<T, C, Modulus> mr)
{
    return o << mr.get();
}

template<typename Traits>
class FFT
{
public:
    typedef typename Traits::type type;

private:
    template<typename It>
    static It fft_r(It first, It last, It tmp_first, It tmp_last, type g)
    {
        std::size_t S = last - first;
        if (S == 1)
            return first;
        else if (S == 2)
        {
            type a = *first;
            type b = *(first + 1);
            *first = a + b;
            *(first + 1) = a - b;
            return first;
        }
        std::size_t H = S / 2;
        It even = tmp_first;
        It odd = tmp_first + H;
        for (std::size_t i = 0; i < H; i++)
        {
            *(even + i) = *(first + 2 * i);
            *(odd + i) = *(first + 2 * i + 1);
        }
        type g2 = g * g;
        even = fft_r(even, odd, first, first + H, g2);
        odd = fft_r(odd, tmp_last, first, first + H, g2);
        if (&*even == &*first)
        {
            swap(first, tmp_first);
            swap(last, tmp_last);
        }
        type p = 1;
        for (std::size_t i = 0; i < H; i++)
        {
            type q = even[i];
            type r = p * odd[i];
            *(first + i) = q + r;
            *(first + i + H) = q - r;
            p *= g;
        }
        return first;
    }

public:
    static std::vector<type> fft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, true));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        return a;
    }

    static std::vector<type> rfft(std::vector<type> a)
    {
        std::size_t S = a.size();
        assert(S > 0 && (S & (S - 1)) == 0); // power of 2
        std::vector<type> tmp(S);
        auto pos = fft_r(a.begin(), a.end(), tmp.begin(), tmp.end(), Traits::generator(S, false));
        if (&*pos == &*tmp.begin())
            a.swap(tmp);
        type iS = Traits::inverse(S);
        for (std::size_t i = 0; i < S; i++)
            a[i] *= iS;
        return a;
    }

    static std::vector<type> convolve(const std::vector<type> &a, const std::vector<type> &b)
    {
        assert(!a.empty());
        assert(!b.empty());
        std::size_t S = 1;
        while (S < a.size() + b.size() - 1)
            S *= 2;

        std::vector<type> pa(S), pb(S);
        std::copy(a.begin(), a.end(), pa.begin());
        std::copy(b.begin(), b.end(), pb.begin());
        std::vector<type> A = fft(pa);
        std::vector<type> B = fft(pb);
        for (std::size_t i = 0; i < S; i++)
            A[i] *= B[i];
        pa = rfft(A);
        pa.resize(a.size() + b.size() - 1);
        return pa;
    }
};

/* These must satisfy:
 * - len is a power of 2
 * - mod is a prime
 * - len divides mod - 1
 * - gen has order len modulo mod
 */
template<typename T, typename C, T mod, T len, T gen>
class fft_traits_mod
{
public:
    typedef MR<T, C, mod> type;

    static type inverse(type value)
    {
        return value.inverse();
    }

    static type generator(std::size_t S, bool invert)
    {
        assert(len % S == 0);
        type g = gen;
        // compute 2^(len / S)
        T s = S;
        for (; s < len; s <<= 1)
            g *= g;
        if (invert)
            g = g.inverse();
        return g;
    }
};

static const ll P1 = 786433;
static const ll P2 = 1179649;
static const ll P12 = P1 * P2;
typedef FFT<fft_traits_mod<int, ll, 786433, 262144, 5> > FFT2p18;
typedef FFT<fft_traits_mod<int, ll, 1179649, 131072, 74> > FFT2p17;

static ll inv1, inv2;

static vi convolve(const vi &a, const vi &b)
{
    typedef FFT2p18::type T1;
    typedef FFT2p17::type T2;
    vector<T1> a1(RA(a)), b1(RA(b));
    vector<T2> a2(RA(a)), b2(RA(b));
    auto c1 = FFT2p18::convolve(a1, b1);
    auto c2 = FFT2p17::convolve(a2, b2);
    vi c(SZ(c1));
    for (int i = 0; i < SZ(c); i++)
    {
        ll v = (c1[i].get() * inv2 + c2[i].get() * inv1) % P12;
        c[i] = v % 1009;
    }
    return c;
}

struct compare_len
{
    bool operator()(const vi &a, const vi &b) const
    {
        return a.size() > b.size();
    }
};

int main(int argc, const char **argv)
{
    inv1 = inverse(P1, P2) * P1;
    inv2 = inverse(P2, P1) * P2;

    redirect(argc, argv);
    int N, M, K;
    cin >> N >> M >> K;
    priority_queue<vi, vector<vi>, compare_len> q;
    vi freq(M);
    for (int i = 0; i < N; i++)
    {
        int x;
        cin >> x;
        freq[x - 1]++;
    }
    for (int x : freq)
    {
        if (x > 0)
            q.push(vi(x + 1, 1));
    }
    while (SZ(q) >= 2)
    {
        vi a = q.top(); q.pop();
        vi b = q.top(); q.pop();
        q.push(convolve(a, b));
    }
    vi c = q.top();
    int ans = (K < SZ(c)) ? c[K] : 0;
    cout << ans << '\n';

    return 0;
}