#include<iostream>
#include<vector>

#define PB push_back
#define MP make_pair
#define F first
#define S second
using namespace std;

const int MAXN = 1e5, SEG = 8e5;
int l[MAXN], r[MAXN], sum[SEG], lazy[SEG], DFSNUM, ans[MAXN];
bool mark[MAXN];
vector<int> v[MAXN];
int n, m;
vector<pair<int, int> > seg[MAXN];

void DFS(int n)
{
	mark[n] = true;
	l[n] = DFSNUM;
	DFSNUM++;
	for(int x : v[n])
		if(!mark[x])
			DFS(x);
	r[n] = DFSNUM;
}

void add(int ql, int qr, int val, int x = 1, int l = 0, int r = n)
{
	if(ql == qr)
		return;
	if(ql <= l && r <= qr)
	{
		lazy[x] += val;
		if(lazy[x] == 0 && val == -1)
			sum[x] = sum[2 * x] + sum[2 * x + 1];
		if(lazy[x] == 1 && val == 1)
			sum[x] = r - l;
		return;
	}
	int mid = (l + r) / 2;
	if(ql < mid)
		add(ql, qr, val, 2 * x, l, mid);
	if(qr > mid)
		add(ql, qr, val, 2 * x + 1, mid, r);
	if(lazy[x] == 0)
		sum[x] = sum[2 * x] + sum[2 * x + 1];
}

void DFS2(int n)
{
	mark[n] = true;
	for(auto p : seg[n])
		add(p.F, p.S, 1);
	ans[n] = sum[1];
	for(int x : v[n])
		if(!mark[x])
			DFS2(x);
	for(auto p : seg[n])
		add(p.F, p.S, -1);
}

int main()
{
	cin >> n >> m;
	for(int i = 0; i < n - 1; i++)
	{
		int a, b;
		cin >> a >> b;
		a--, b--;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	DFS(0);
	while(m--)
	{
		int a, b;
		cin >> a >> b;
		a--, b--;
		seg[a].PB(MP(l[b], r[b]));
		seg[b].PB(MP(l[a], r[a]));
	}
	for(int i = 0; i < n; i++)
		if(seg[i].size())
			seg[i].PB(MP(l[i], r[i]));
	fill(mark, mark + MAXN, 0);
	DFS2(0);
	for(int i = 0; i < n; i++)
		cout << max(0, ans[i] - 1) << ' ';
	cout << endl;
	return 0;
}


#include<iostream>
#include<vector>

#define PB push_back
#define MP make_pair
#define F first
#define S second
using namespace std;

const int MAXN = 1e5, SEG = 4e5;
int l[MAXN], r[MAXN], sum[SEG], lazy[SEG], DFSNUM, ans[MAXN];
bool mark[MAXN];
vector<int> v[MAXN];
int n, m;
vector<pair<int, int> > seg[MAXN];

void DFS(int n)
{
	mark[n] = true;
	l[n] = DFSNUM;
	DFSNUM++;
	for(int x : v[n])
		if(!mark[x])
			DFS(x);
	r[n] = DFSNUM;
}

void add(int ql, int qr, int val, int x = 1, int l = 0, int r = n)
{
	if(ql == qr)
		return;
	if(ql <= l && r <= qr)
	{
		lazy[x] += val;
		if(lazy[x] == 0 && val == -1)
			sum[x] = sum[2 * x] + sum[2 * x + 1];
		if(lazy[x] == 1 && val == 1)
			sum[x] = r - l;
		return;
	}
	int mid = (l + r) / 2;
	if(ql < mid)
		add(ql, qr, val, 2 * x, l, mid);
	if(qr > mid)
		add(ql, qr, val, 2 * x + 1, mid, r);
	if(lazy[x] == 0)
		sum[x] = sum[2 * x] + sum[2 * x + 1];
}

void DFS2(int n)
{
	mark[n] = true;
	for(auto p : seg[n])
		add(p.F, p.S, 1);
	ans[n] = sum[1];
	for(int x : v[n])
		if(!mark[x])
			DFS2(x);
	for(auto p : seg[n])
		add(p.F, p.S, -1);
}

int main()
{
	cin >> n >> m;
	for(int i = 0; i < n - 1; i++)
	{
		int a, b;
		cin >> a >> b;
		a--, b--;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	DFS(0);
	while(m--)
	{
		int a, b;
		cin >> a >> b;
		a--, b--;
		seg[a].PB(MP(l[b], r[b]));
		seg[b].PB(MP(l[a], r[a]));
	}
	for(int i = 0; i < n; i++)
		if(seg[i].size())
			seg[i].PB(MP(l[i] + 1, r[i]));
	fill(mark, mark + MAXN, 0);
	DFS2(0);
	for(int i = 0; i < n; i++)
		cout << ans[i] << ' ';
	cout << endl;
	return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;

const int N = int(1e5) + 50;

struct tree
{
	tree *lc, *rc;
	int l, r, cnt, delta;
	tree (int _l, int _r) : l(_l), r(_r), lc(0), rc(0), cnt(0), delta(0) {}
	void inc (int d)
	{
		delta += d;
		if (delta) cnt = r - l + 1; else
			cnt = lc ? lc->cnt + rc->cnt : 0;
	}
	void init ()
	{
		if (l == r) return;
		int m = (l + r) / 2;
		(lc = new tree(l, m))->init();
		(rc = new tree(m + 1, r))->init();
	}
	void inc (int ql, int qr, int d)
	{
		if (ql <= l && r <= qr) { inc(d); return; }
		int m = (l + r) / 2;
		if (ql <= m) lc->inc(ql, qr, d);
		if (qr > m) rc->inc(ql, qr, d);
		cnt = delta ? r - l + 1 : lc->cnt + rc->cnt;
	}
	int count (int ql, int qr)
	{
		if (ql <= l && r <= qr) return cnt;
		if (delta) return delta * (min(qr, r) - max(ql, l) + 1);
		int m = (l + r) / 2, re = 0;
		if (ql <= m) re += lc->count(ql, qr);
		if (qr > m)  re += rc->count(ql, qr);
		return re;
	}
} *rt;

struct edge { int t; edge *n; } eb[N * 2], *e[N], *ec = eb;
inline void add_edge (int s, int t)
{
	*ec = (edge){t, e[s]}; e[s] = ec++;
	*ec = (edge){s, e[t]}; e[t] = ec++;
}

int spos[N], epos[N], dep[N], size[N];
vector<int> pal[N];

inline void init (int x, int ax)
{
	static int ts = 0;
	spos[x] = ++ts;
	for (edge *i = e[x]; i; i = i->n)
		if (i->t != ax) init(i->t, x);
	epos[x] = ++ts;
}

int f[N], res[N];
inline int find (int x) { return (f[x] == x) ? x : (f[x] = find(f[x])); }

inline void solve (int x, int ax)
{
	if (pal[x].size())
	{
		for (int y : pal[x])
			rt->inc(spos[y], epos[y], +1);
		rt->inc(spos[x], epos[x], +1);
	}
	res[x] = rt->cnt;
	for (edge *i = e[x]; i; i = i->n)
		if (i->t != ax) solve(i->t, x);
	if (res[x] != rt->cnt)
		throw;
	if (pal[x].size())
	{
		for (int y : pal[x])
			rt->inc(spos[y], epos[y], -1);
		rt->inc(spos[x], epos[x], -1);
	}
}

int n, m;

int main ()
{
#ifdef LOCAL
	freopen("in", "r", stdin);
#endif
	scanf("%d%d", &n, &m);
	for (int i = 1; i < n; ++i)
	{
		int a, b;
		scanf("%d%d", &a, &b);
		add_edge(a, b);
	}
	init(1, 0);
	(rt = new tree(1, n * 2))->init();
	for (int i = 1, a, b; i <= m; ++i)
	{
		scanf("%d%d", &a, &b);
		pal[a].push_back(b);
		pal[b].push_back(a);
	}
	solve(1, 0);
	for (int i = 1; i <= n; ++i)
		printf("%d%c", max(0, res[i] / 2 - 1), " \n"[i == n]);
	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <stack>
#include <ctime>
#include <unordered_map>
#pragma comment (linker, "/STACK:256000000")

using namespace std;

const int maxN = 110000;
vector < int > g[maxN];
int n, m;
int a[maxN], b[maxN];
int cnt[maxN];

vector < int > marked[maxN];
bool used[maxN];
int parent[maxN];

set < int > *s[maxN];

void dfs(int v) {
	used[v] = true;
	if (parent[v] == 0) {
		if (marked[v].size() > 0) {
			parent[v] = v;
		}
	}
	cnt[v] = 1;
	for (int i = 0; i < g[v].size(); ++i) {
		if (used[g[v][i]]) {
			continue;
		}
		if (parent[v] != 0) {
			parent[g[v][i]] = parent[v];
		}
		dfs(g[v][i]);
		cnt[v] += cnt[g[v][i]];
	}
}

void solve(int v) {
	used[v] = true;

	vector < int > candidates;
	for (int i = 0; i < g[v].size(); ++i) {
		if (!used[g[v][i]]) {
			solve(g[v][i]);
			candidates.push_back(g[v][i]);
		}
	}

	if (parent[v] != 0) {
		if (candidates.size() == 0) {
			s[v] = new set < int > ();
		} else {
			int id = 0;
			for (int i = 0; i < candidates.size(); ++i) {
				if (s[candidates[i]]->size() > s[candidates[id]]->size()) {
					id = i;
				}
			}
			s[v] = s[candidates[id]];
			for (int i = 0; i < candidates.size(); ++i) {
				if (id == i) {
					continue;
				}
				int u = candidates[i];
				for (set < int > ::iterator it = s[u]->begin(); it != s[u]->end(); ++it) {
					s[v]->insert(*it);
				}
			}
		}
		for (int i = 0; i < marked[v].size(); ++i) {
			int p = parent[marked[v][i]];
			s[v]->insert(p);
		}
	}
	if (parent[v] == v) {
		s[v]->erase(v);
	}
}

map < int, int > M;

int res[maxN];

void calc(int v, int &score) {
	used[v] = true;
	for (int i = 0; i < marked[v].size(); ++i) {
		int p = parent[marked[v][i]];
		++M[p];
		if (M[p] == 1) {
			score += cnt[p];
		}
	}

	res[v] = score - 1;

	for (int i = 0; i < g[v].size(); ++i) {
		if (used[g[v][i]]) {
			continue;
		}
		calc(g[v][i], score);
	}

	for (int i = 0; i < marked[v].size(); ++i) {
		int p = parent[marked[v][i]];
		--M[p];
		if (M[p] == 0) {
			score -= cnt[p];
		}
	}
}

/*int calc(int v) {
	if (v == 0) {
		return 0;
	}
	if (M.count(v)) {
		return M[v];
	}

	int res = cnt[v];
	for (set < int > ::iterator it = s[v]->begin(); it != s[v]->end(); ++it) {
		res += cnt[*it];
	}
	return M[v] = res - 1;
}*/

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);

	scanf("%d%d", &n, &m);
	for (int i = 1; i < n; ++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].push_back(v);
		g[v].push_back(u);
	}

	for (int i = 1; i <= m; ++i) {
		scanf("%d%d", &a[i], &b[i]);
		marked[a[i]].push_back(a[i]);
		marked[a[i]].push_back(b[i]);
		marked[b[i]].push_back(a[i]);
		marked[b[i]].push_back(b[i]);
	}

	dfs(1);
	memset(used, 0, sizeof(used));

	//solve(1);
	int score = 0;
	calc(1, score);

	for (int i = 1; i <= n; ++i) {
		if (parent[i] == 0) {
			res[i] = 0;
		}
		printf("%d ", res[i]);
	}
	printf("\n");

	return 0;
}


#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <cmath>
#include <stack>
#include <ctime>
#include <unordered_map>
#pragma comment (linker, "/STACK:256000000")

using namespace std;

const int maxN = 110000;
vector < int > g[maxN];
int n, m;
int a[maxN], b[maxN];
int cnt[maxN];

vector < int > marked[maxN];
bool used[maxN];

int pos[maxN], L[maxN], R[maxN], id = 0;

void dfs(int v) {
	used[v] = true;
	++id;
	pos[v] = id;
	L[v] = id;
	for (int i = 0; i < g[v].size(); ++i) {
		if (used[g[v][i]]) {
			continue;
		}
		dfs(g[v][i]);
	}
	R[v] = id;
}

int res[maxN];

pair < int, int > t[4 * maxN];
int add[4 * maxN];

void init(int i, int l, int r) {
	if (l == r) {
		t[i] = make_pair(0, r - l + 1);
		return ;
	}
	init(2 * i, l, (l + r) / 2);
	init(2 * i + 1, (l + r) / 2 + 1, r);
	t[i].first = 0;
	t[i].second = r - l + 1;
}

void update(int i, int l, int r, int cl, int cr, int delta) {
	if (l == cl && r == cr) {
		t[i].first += delta;
		add[i] += delta;
		return ;
	}

	if (cl > (l + r) / 2) {
		update(2 * i + 1, (l + r) / 2 + 1, r, cl, cr, delta);
	} else if (cr <= (l + r) / 2) {
		update(2 * i, l, (l + r) / 2, cl, cr, delta);
	} else {
		update(2 * i, l, (l + r) / 2, cl, (l + r) / 2, delta);
		update(2 * i + 1, (l + r) / 2 + 1, r, (l + r) / 2 + 1, cr, delta);
	}

	t[i].first = min(t[2 * i].first, t[2 * i + 1].first);

	t[i].second = 0;
	if (t[2 * i].first == t[i].first) {
		t[i].second += t[2 * i].second;
	}
	if (t[2 * i + 1].first == t[i].first) {
		t[i].second += t[2 * i + 1].second;
	}

	t[i].first += add[i];
}

int get() {
	if (t[1].first == 0) {
		return t[1].second;
	} else {
		return 0;
	}
}

void calc(int v) {
	used[v] = true;
	for (int i = 0; i < marked[v].size(); ++i) {
		int u = marked[v][i];
		update(1, 1, n, L[u], R[u], +1);
	}

	res[v] = max(0, n - get() - 1);

	for (int i = 0; i < g[v].size(); ++i) {
		if (!used[g[v][i]]) {
			calc(g[v][i]);
		}
	}

	for (int i = 0; i < marked[v].size(); ++i) {
		int u = marked[v][i];
		update(1, 1, n, L[u], R[u], -1);
	}
}

int main() {
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);

	scanf("%d%d", &n, &m);
	for (int i = 1; i < n; ++i) {
		int u, v;
		scanf("%d%d", &u, &v);
		g[u].push_back(v);
		g[v].push_back(u);
	}

	for (int i = 1; i <= m; ++i) {
		scanf("%d%d", &a[i], &b[i]);
		marked[a[i]].push_back(a[i]);
		marked[a[i]].push_back(b[i]);
		marked[b[i]].push_back(a[i]);
		marked[b[i]].push_back(b[i]);
	}

	dfs(1);
	memset(used, 0, sizeof(used));
	int score = 0;
	init(1, 1, n);
	calc(1);

	for (int i = 1; i <= n; ++i) {
		printf("%d ", res[i]);
	}
	printf("\n");

	return 0;
}


#include<cstdio>
#include<vector>
using namespace std;
#define tree int t,int l,int r
#define left t*2,l,mid
#define right t*2+1,mid+1,r
#define M int mid=(l+r)/2
#define pr pair<int,int>
#define mk make_pair
#define pb push_back
#define X first
#define Y second
#define N 100005
vector<int > ed[N];
vector<pr > e[N];
int a[N*4],c[N*4],d[N],L[N],R[N],ans[N],n,m,x,y,len,v;
void dfs(int x,int last)
{
	d[++len]=x,L[x]=len;
	for (int y:ed[x]) if (y-last) dfs(y,x);
	R[x]=len;
}
void build(tree){a[t]=r-l+1; if (l==r) return; M; build(left),build(right);}
void add(tree,int ll,int rr)
{
	if (l==ll && r==rr){c[t]+=v,a[t]=c[t]?0:r-l?a[t*2]+a[t*2+1]:1; return;} M;
	if (rr<=mid) add(left,ll,rr); else if (ll>mid) add(right,ll,rr);
	else add(left,ll,mid),add(right,mid+1,rr); a[t]=c[t]?0:a[t*2]+a[t*2+1];
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<n;i++) scanf("%d%d",&x,&y),ed[x].pb(y),ed[y].pb(x);
	dfs(1,0); build(1,1,n);
	for (int i=1;i<=m;i++) scanf("%d%d",&x,&y),
		e[L[x]].pb(mk(x,y)),e[R[x]+1].pb(mk(x,-y)),
		e[L[y]].pb(mk(x,y)),e[R[y]+1].pb(mk(x,-y));
	for (int i=1;i<=n;i++){
		for (pr j:e[i]){
			v=1; if (j.Y<0) j.Y*=-1,v=-1;
			add(1,1,n,L[j.X],R[j.X]),add(1,1,n,L[j.Y],R[j.Y]);
			}
		v=1,add(1,1,n,i,i),ans[d[i]]+=n-a[1]-1,v=-1,add(1,1,n,i,i);
		}
	for (int i=1;i<=n;i++) printf("%d%s",ans[i],i<n?" ":"\n"); return 0;
}


/*
 * File:      main.cpp
 * Author:    Hrayr [HarHro94]
 * Problem:
 * IDE:       Visual C++ 2012
 */
#pragma comment(linker, "/STACK:66777216")
#define _CRT_SECURE_NO_WARNINGS
#include <functional>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <fstream>
#include <cassert>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <string>
#include <vector>
#include <ctime>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
using namespace std;

typedef long long LL;
typedef long double LD;
#define pb push_back
#define mp make_pair
#define all(v) (v).begin(), (v).end()
#define sz(v) (int)(v).size()

const int N = 100007;

struct segTree
{
    pair<int, int> T[8 * N]; // (minimum, cnt of minimum)
    int add[8 * N];

    segTree()
    {
        for (int i = 0; i < 8 * N; ++i)
        {
            T[i].first = 1 << 29;
            T[i].second = 0;
            add[i] = 0;
        }
    }

    inline pair<int, int> get(int v)
    {
        return mp(T[v].first + add[v], T[v].second);
    }

    inline pair<int, int> combine(const pair<int, int> &left, const pair<int, int> &right)
    {
        pair<int, int> ret;
        if (left.first == right.first)
        {
            ret.first = left.first;
            ret.second = left.second + right.second;
        }
        else if (left.first < right.first)
        {
            ret = left;
        }
        else
        {
            ret = right;
        }
        return ret;
    }

    inline void fix(int v)
    {
        T[v] = combine(get(2 * v), get(2 * v + 1));
    }

    inline void push(int v)
    {
        T[v].first += add[v];
        add[2 * v] += add[v];
        add[2 * v + 1] += add[v];
        add[v] = 0;
    }

    void build(int v, int tl, int tr)
    {
        if (tl == tr)
        {
            T[v] = mp(0, 1);
            return;
        }
        int tm = (tl + tr) >> 1;
        build(2 * v, tl, tm);
        build(2 * v + 1, tm + 1, tr);
        fix(v);
    }

    void update(int v, int tl, int tr, int l, int r, int delta)
    {
        if (tl == l && tr == r)
        {
            add[v] += delta;
            return;
        }
        push(v);
        int tm = (tl + tr) >> 1;
        if (r <= tm)
        {
            update(2 * v, tl, tm, l, r, delta);
        }
        else if (l > tm)
        {
            update(2 * v + 1, tm + 1, tr, l, r, delta);
        }
        else
        {
            update(2 * v, tl, tm, l, tm, delta);
            update(2 * v + 1, tm + 1, tr, tm + 1, r, delta);
        }
        fix(v);
    }

    pair<int, int> query(int v, int tl, int tr, int l, int r)
    {
        push(v);
        if (tl == l && tr == r)
        {
            return T[v];
        }
        int tm = (tl + tr) >> 1;
        pair<int, int> ret;
        if (r <= tm)
        {
            ret = query(2 * v, tl, tm, l, r);
        }
        else if (l > tm)
        {
            ret = query(2 * v + 1, tm + 1, tr, l, r);
        }
        else
        {
            ret = combine(query(2 * v, tl, tm, l, tm), query(2 * v + 1, tm + 1, tr, tm + 1, r));
        }
        fix(v);
        return ret;
    }
} tree;

vector<int> G[N], Q[N];
int n, m, id[N], L[N], R[N], ans[N];
int timer;

void dfsDp(int u, int p = 0)
{
    for (int to : G[u])
    {
        if (to != p)
        {
            dfsDp(to, u);
            L[u] = min(L[u], L[to]);
        }
    }
    ++timer;
    R[u] = id[u] = timer;
    L[u] = min(L[u], R[u]);
}

void dfs(int u, int p = 0)
{
    for (int v : Q[u])
    {
        tree.update(1, 1, n, L[v], R[v], +1);
    }
    if (sz(Q[u]))
    {
        tree.update(1, 1, n, L[u], R[u], +1);
    }
    pair<int, int> cur = tree.query(1, 1, n, 1, n);
    if (cur.first == 0)
    {
        ans[u] = n - cur.second - 1;
        if (ans[u] == -1)
        {
            ans[u] = 0;
        }
    }
    else
    {
        ans[u] = n - 1;
    }
    for (int to : G[u])
    {
        if (to != p)
        {
            dfs(to, u);
        }
    }
    for (int v : Q[u])
    {
        tree.update(1, 1, n, L[v], R[v], -1);
    }
    if (sz(Q[u]))
    {
        tree.update(1, 1, n, L[u], R[u], -1);
    }
}

int main()
{
#ifdef harhro94
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif

    scanf("%d%d", &n, &m);
    for (int i = 1; i < n; ++i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].pb(v), G[v].pb(u);
    }
    for (int i = 0; i < m; ++i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        Q[u].pb(v), Q[v].pb(u);
    }
    tree.build(1, 1, n);
    fill(L, L + N, 1 << 29);
    dfsDp(1);
    dfs(1);
    for (int i = 1; i <= n; ++i)
    {
        printf("%d ", ans[i]);
    }

#ifdef harhro94
    cerr << fixed << setprecision(3) << "\nExecution time = " << clock() / 1000.0 << "s\n";
#endif
    return 0;
}


#include <stdio.h>
#include <vector>

#define MAX_N 100005
#define RIGHT 131072
#define SIZE 262155

int M, N, Pre;
int Ans[MAX_N], L[MAX_N], R[MAX_N];
using namespace std;
vector<int> E[MAX_N], Q[MAX_N];

class T
{
public:
    int count[SIZE], used[SIZE];
    int getCount();
    void update(int l, int r, int v, int n, int a, int b);
} Tree;

void T::update(int l, int r, int v, int n, int a, int b)
{
    if(a > r || b < l)
        return;
    if(a >= l && b <= r)
        count[n] += v;
    else
    {
        int mid = (a + b) / 2;
        update(l, r, v, 2*n, a, mid);
        update(l, r, v, 2*n + 1, mid + 1, b);
    }

    if(count[n] > 0)
        used[n] = b - a + 1;
    else
        used[n] = a == b ? 0 : used[2*n] + used[2*n + 1];
}

void in()
{
    scanf("%d %d", &N, &M);

    for(int i = 1; i < N; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        E[a].push_back(b);
        E[b].push_back(a);
    }

    for(int i = 0; i < M; i++)
    {
        int a, b;
        scanf("%d %d", &a, &b);
        Q[a].push_back(a);
        Q[a].push_back(b);
        Q[b].push_back(a);
        Q[b].push_back(b);
    }
}

void dfs(int n, int p)
{
    L[n] = ++Pre;

    for(int v : E[n])
        if(v != p)
            dfs(v, n);

    R[n] = Pre;
}

void dfs2(int n, int p)
{
    for(int v : Q[n])
        Tree.update(L[v], R[v], 1, 1, 1, RIGHT);

    Ans[n] = max(Tree.used[1] - 1, 0);

    for(int v : E[n])
        if(v != p)
            dfs2(v, n);

    for(int v : Q[n])
        Tree.update(L[v], R[v], -1, 1, 1, RIGHT);
}

int main()
{
    in();
    dfs(1, 0);
    dfs2(1, 0);

    for(int i = 1; i <= N; i++)
        printf("%d ", Ans[i]);

    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

const int MAXN = 100010 ;

vector<int> e[MAXN] ;
vector<int> p[MAXN] ;
int n , m ;
int res[MAXN] ;
int step ,tl[MAXN],tr[MAXN];
struct node{
    int l,r,flag,s;
}t[MAXN<<2] ;

void dfs1(int u,int fa){
    tl[u]=step++;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue;
        dfs1(v,u);
    }
    tr[u]=step-1;
}

void build(int k,int l,int r){
    t[k].l=l;t[k].r=r;
    t[k].flag=t[k].s=0;
    if (l==r) return ;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r) ;
}

void modify(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag--;
        if (t[k].flag==0)
            t[k].s = t[k<<1].s + t[k<<1|1].s ;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) modify(k<<1,l,r);
    else if (l>mid) modify(k<<1|1,l,r);
    else{
        modify(k<<1,l,mid);
        modify(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void insert(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag++;
        t[k].s=r-l+1;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) insert(k<<1,l,r);
    else if (l>mid) insert(k<<1|1,l,r);
    else{
        insert(k<<1,l,mid);
        insert(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void dfs2(int u,int fa){
    if (p[u].size()>0)
        insert(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        insert(1,tl[v],tr[v]);
    }
    res[u]=t[1].s;
    if (res[u]>0) res[u]--;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue ;
        dfs2(v,u);
    }
    if (p[u].size()>0)
        modify(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        modify(1,tl[v],tr[v]);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<n;i++){
        int u,v;scanf("%d%d",&u,&v);
        u--;v--;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    for (int i=0;i<m;i++){
        int a,b;scanf("%d%d",&a,&b);
        a--;b--;
        p[a].push_back(b);
        p[b].push_back(a);
    }
    step=0;
    dfs1(0,-1);
    build(1,0,n-1);
    dfs2(0,-1);
    for (int i=0;i<n;i++)
        printf("%d%c",res[i],(i==n-1)?'\n':' ');
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

const int MAXN = 100010 ;

vector<int> e[MAXN] ;
vector<int> p[MAXN] ;
int n , m ;
int res[MAXN] ;
int step ,tl[MAXN],tr[MAXN];
struct node{
    int l,r,flag,s;
}t[1000000] ;

void dfs1(int u,int fa){
    tl[u]=step++;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue;
        dfs1(v,u);
    }
    tr[u]=step-1;
}

void build(int k,int l,int r){
    t[k].l=l;t[k].r=r;
    t[k].flag=t[k].s=0;
    if (l==r) return ;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r) ;
}

void modify(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag--;
        if (t[k].flag==0)
            t[k].s = t[k<<1].s + t[k<<1|1].s ;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) modify(k<<1,l,r);
    else if (l>mid) modify(k<<1|1,l,r);
    else{
        modify(k<<1,l,mid);
        modify(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void insert(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag++;
        t[k].s=r-l+1;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) insert(k<<1,l,r);
    else if (l>mid) insert(k<<1|1,l,r);
    else{
        insert(k<<1,l,mid);
        insert(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void dfs2(int u,int fa){
    if (p[u].size()>0)
        insert(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        insert(1,tl[v],tr[v]);
    }
    res[u]=t[1].s;
    if (res[u]>0) res[u]--;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue ;
        dfs2(v,u);
    }
    if (p[u].size()>0)
        modify(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        modify(1,tl[v],tr[v]);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<n;i++){
        int u,v;scanf("%d%d",&u,&v);
        u--;v--;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    for (int i=0;i<m;i++){
        int a,b;scanf("%d%d",&a,&b);
        a--;b--;
        p[a].push_back(b);
        p[b].push_back(a);
    }
    step=0;
    dfs1(0,-1);
    build(1,0,n-1);
    dfs2(0,-1);
    for (int i=0;i<n;i++)
        printf("%d%c",res[i],(i==n-1)?'\n':' ');
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

const int MAXN = 100010 ;

vector<int> e[MAXN] ;
vector<int> p[MAXN] ;
int n , m ;
int res[MAXN] ;
int step ,tl[MAXN],tr[MAXN];
struct node{
    int l,r,flag,s;
}t[MAXN<<3] ;

void dfs1(int u,int fa){
    tl[u]=step++;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue;
        dfs1(v,u);
    }
    tr[u]=step-1;
}

void build(int k,int l,int r){
    t[k].l=l;t[k].r=r;
    t[k].flag=t[k].s=0;
    if (l==r) return ;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r) ;
}

void modify(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag--;
        if (t[k].flag==0)
            t[k].s = t[k<<1].s + t[k<<1|1].s ;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) modify(k<<1,l,r);
    else if (l>mid) modify(k<<1|1,l,r);
    else{
        modify(k<<1,l,mid);
        modify(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void insert(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag++;
        t[k].s=r-l+1;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) insert(k<<1,l,r);
    else if (l>mid) insert(k<<1|1,l,r);
    else{
        insert(k<<1,l,mid);
        insert(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void dfs2(int u,int fa){
    if (p[u].size()>0)
        insert(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        insert(1,tl[v],tr[v]);
    }
    res[u]=t[1].s;
    if (res[u]>0) res[u]--;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue ;
        dfs2(v,u);
    }
    if (p[u].size()>0)
        modify(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        modify(1,tl[v],tr[v]);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<n;i++){
        int u,v;scanf("%d%d",&u,&v);
        u--;v--;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    for (int i=0;i<m;i++){
        int a,b;scanf("%d%d",&a,&b);
        a--;b--;
        p[a].push_back(b);
        p[b].push_back(a);
    }
    step=0;
    dfs1(0,-1);
    build(1,0,n-1);
    dfs2(0,-1);
    for (int i=0;i<n;i++)
        printf("%d%c",res[i],(i==n-1)?'\n':' ');
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

const int MAXN = 100010 ;

vector<int> e[MAXN] ;
vector<int> p[MAXN] ;
int n , m ;
int res[MAXN] ;
int step ,tl[MAXN],tr[MAXN];
struct node{
    int l,r,flag,s;
}t[MAXN<<2] ;

void dfs1(int u,int fa){
    tl[u]=step++;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue;
        dfs1(v,u);
    }
    tr[u]=step-1;
}

void build(int k,int l,int r){
    t[k].l=l;t[k].r=r;
    t[k].flag=t[k].s=0;
    if (l==r) return ;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r) ;
}

void modify(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag--;
        if (t[k].flag==0)
        {
            if (l != r)
                t[k].s = t[k<<1].s + t[k<<1|1].s ;
            else
                t[k].s = 0 ;
        }
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) modify(k<<1,l,r);
    else if (l>mid) modify(k<<1|1,l,r);
    else{
        modify(k<<1,l,mid);
        modify(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void insert(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag++;
        t[k].s=r-l+1;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) insert(k<<1,l,r);
    else if (l>mid) insert(k<<1|1,l,r);
    else{
        insert(k<<1,l,mid);
        insert(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void dfs2(int u,int fa){
    if (p[u].size()>0)
        insert(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        insert(1,tl[v],tr[v]);
    }
    res[u]=t[1].s;
    if (res[u]>0) res[u]--;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue ;
        dfs2(v,u);
    }
    if (p[u].size()>0)
        modify(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        modify(1,tl[v],tr[v]);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<n;i++){
        int u,v;scanf("%d%d",&u,&v);
        u--;v--;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    for (int i=0;i<m;i++){
        int a,b;scanf("%d%d",&a,&b);
        a--;b--;
        p[a].push_back(b);
        p[b].push_back(a);
    }
    step=0;
    dfs1(0,-1);
    build(1,0,n-1);
    dfs2(0,-1);
    for (int i=0;i<n;i++)
        printf("%d%c",res[i],(i==n-1)?'\n':' ');
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

const int MAXN = 100010 ;

vector<int> e[MAXN] ;
vector<int> p[MAXN] ;
int n , m ;
int res[MAXN] ;
int step ,tl[MAXN],tr[MAXN];
struct node{
    int l,r,flag,s;
}t[MAXN<<2] ;

void dfs1(int u,int fa){
    tl[u]=step++;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue;
        dfs1(v,u);
    }
    tr[u]=step-1;
}

void build(int k,int l,int r){
    t[k].l=l;t[k].r=r;
    t[k].flag=t[k].s=0;
    if (l==r) return ;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r) ;
}

void modify(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag--;
        if (t[k].flag==0)
            t[k].s = t[k<<1].s + t[k<<1|1].s ;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) modify(k<<1,l,r);
    else if (l>mid) modify(k<<1|1,l,r);
    else{
        modify(k<<1,l,mid);
        modify(k<<1|1,mid+1,r);
    }
    if (t[k].l==t[k].r) return ;
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void insert(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag++;
        t[k].s=r-l+1;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) insert(k<<1,l,r);
    else if (l>mid) insert(k<<1|1,l,r);
    else{
        insert(k<<1,l,mid);
        insert(k<<1|1,mid+1,r);
    }
    if (t[k].l==t[k].r) return ;
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void dfs2(int u,int fa){
    if (p[u].size()>0)
        insert(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        insert(1,tl[v],tr[v]);
    }
    res[u]=t[1].s;
    if (res[u]>0) res[u]--;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue ;
        dfs2(v,u);
    }
    if (p[u].size()>0)
        modify(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        modify(1,tl[v],tr[v]);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<n;i++){
        int u,v;scanf("%d%d",&u,&v);
        u--;v--;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    for (int i=0;i<m;i++){
        int a,b;scanf("%d%d",&a,&b);
        a--;b--;
        p[a].push_back(b);
        p[b].push_back(a);
    }
    step=0;
    dfs1(0,-1);
    build(1,0,n-1);
    dfs2(0,-1);
    for (int i=0;i<n;i++)
        printf("%d%c",res[i],(i==n-1)?'\n':' ');
    return 0;
}


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <iostream>

using namespace std;

const int MAXN = 100010 ;

vector<int> e[MAXN] ;
vector<int> p[MAXN] ;
int n , m ;
int res[MAXN] ;
int step ,tl[MAXN],tr[MAXN];
struct node{
    int l,r,flag,s;
}t[MAXN<<2] ;

void dfs1(int u,int fa){
    tl[u]=step++;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue;
        dfs1(v,u);
    }
    tr[u]=step-1;
}

void build(int k,int l,int r){
    t[k].l=l;t[k].r=r;
    t[k].flag=t[k].s=0;
    if (l==r) return ;
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r) ;
}

void modify(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag--;
        if (t[k].flag==0 && l!=r)
            t[k].s = t[k<<1].s + t[k<<1|1].s ;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) modify(k<<1,l,r);
    else if (l>mid) modify(k<<1|1,l,r);
    else{
        modify(k<<1,l,mid);
        modify(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void insert(int k,int l,int r){
    if (t[k].l==l && t[k].r==r){
        t[k].flag++;
        t[k].s=r-l+1;
        return ;
    }
    int mid=(t[k].l+t[k].r)>>1;
    if (r<=mid) insert(k<<1,l,r);
    else if (l>mid) insert(k<<1|1,l,r);
    else{
        insert(k<<1,l,mid);
        insert(k<<1|1,mid+1,r);
    }
    if (t[k].flag==0)
        t[k].s = t[k<<1].s + t[k<<1|1].s;
}

void dfs2(int u,int fa){
    if (p[u].size()>0)
        insert(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        insert(1,tl[v],tr[v]);
    }
    res[u]=t[1].s;
    if (res[u]>0) res[u]--;
    for (int i=0;i<e[u].size();i++){
        int v=e[u][i];
        if (v==fa) continue ;
        dfs2(v,u);
    }
    if (p[u].size()>0)
        modify(1,tl[u],tr[u]);
    for (int i=0;i<p[u].size();i++){
        int v=p[u][i];
        modify(1,tl[v],tr[v]);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<n;i++){
        int u,v;scanf("%d%d",&u,&v);
        u--;v--;
        e[u].push_back(v);
        e[v].push_back(u);
    }
    for (int i=0;i<m;i++){
        int a,b;scanf("%d%d",&a,&b);
        a--;b--;
        p[a].push_back(b);
        p[b].push_back(a);
    }
    step=0;
    dfs1(0,-1);
    build(1,0,n-1);
    dfs2(0,-1);
    for (int i=0;i<n;i++)
        printf("%d%c",res[i],(i==n-1)?'\n':' ');
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define F first
#define S second
const int maxn=100010;

int n,m;
vector <int> v[maxn];
int st[maxn],fn[maxn];
vector <pair<int,int> > op[maxn];
int cnt;

void dfs(int x,int par)
{
	st[x]=cnt; cnt++;
	for (int i=0;i<v[x].size();i++)
		if (v[x][i]!=par) dfs(v[x][i],x);
	fn[x]=cnt;
}

int tedm[maxn*4],segm[maxn*4],laz[maxn];

void add(int ql,int qr,int val,int l=0,int r=n,int x=1)
{
	if (ql<=l && r<=qr)
	{
		segm[x]+=val;
		laz[x]+=val;
		return;
	}
	laz[x*2]+=laz[x];
	laz[x*2+1]+=laz[x];
	segm[x*2]+=laz[x];
	segm[x*2+1]+=laz[x];
	laz[x]=0;
	int mid=(l+r)/2;
	if (ql<mid) add(ql,qr,val,l,mid,x*2+0);
	if (qr>mid) add(ql,qr,val,mid,r,x*2+1);
	segm[x]=min(segm[x*2],segm[x*2+1]);
	tedm[x]=0;
	if (segm[x*2]==segm[x])   tedm[x]+=tedm[x*2];
	if (segm[x*2+1]==segm[x]) tedm[x]+=tedm[x*2+1];
}
void make_tree(int l=0,int r=n,int x=1)
{
	tedm[x]=r-l;
	if (r-l<2) return;
	int mid=(l+r)/2;
	make_tree(l,mid,x*2);
	make_tree(mid,r,x*2+1);
}

int ans[maxn];
void solve(int x,int par)
{
	for (int i=0;i<op[x].size();i++)
	{
		add(st[op[x][i].F],fn[op[x][i].F],1);
		add(st[op[x][i].S],fn[op[x][i].S],1);
	}
	ans[x]=n-1;
	if (segm[1]==0) ans[x]-=tedm[1];
	for (int i=0;i<v[x].size();i++)
		if (v[x][i]!=par) solve(v[x][i],x);
	for (int i=0;i<op[x].size();i++)
	{
		add(st[op[x][i].F],fn[op[x][i].F],-1);
		add(st[op[x][i].S],fn[op[x][i].S],-1);
	}
}

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

	cin >> n >> m;
	for (int i=0;i<n-1;i++)
	{
		int x,y;
		cin >> x >> y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(1,0);

	for (int i=0;i<m;i++)
	{
		int x,y;
		cin >> x >> y;
		op[x].push_back(mp(x,y));
		op[y].push_back(mp(x,y));
	}
	make_tree();
	solve(1,0);

	for (int i=1;i<=n;i++) cout << max(0,ans[i]) << " ";
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define F first
#define S second
const int maxn=100010;

int n,m;
vector <int> v[maxn];
int st[maxn],fn[maxn];
vector <pair<int,int> > op[maxn];
int cnt;

void dfs(int x,int par)
{
	st[x]=cnt; cnt++;
	for (int i=0;i<v[x].size();i++)
		if (v[x][i]!=par) dfs(v[x][i],x);
	fn[x]=cnt;
}

int tedm[maxn*4],segm[maxn*4],laz[maxn*4];

void add(int ql,int qr,int val,int l=0,int r=n,int x=1)
{
	if (ql<=l && r<=qr)
	{
		segm[x]+=val;
		laz[x]+=val;
		return;
	}
	laz[x*2]+=laz[x];
	laz[x*2+1]+=laz[x];
	segm[x*2]+=laz[x];
	segm[x*2+1]+=laz[x];
	laz[x]=0;
	int mid=(l+r)/2;
	if (ql<mid) add(ql,qr,val,l,mid,x*2+0);
	if (qr>mid) add(ql,qr,val,mid,r,x*2+1);
	segm[x]=min(segm[x*2],segm[x*2+1]);
	tedm[x]=0;
	if (segm[x*2]==segm[x])   tedm[x]+=tedm[x*2];
	if (segm[x*2+1]==segm[x]) tedm[x]+=tedm[x*2+1];
}
void make_tree(int l=0,int r=n,int x=1)
{
	tedm[x]=r-l;
	if (r-l<2) return;
	int mid=(l+r)/2;
	make_tree(l,mid,x*2);
	make_tree(mid,r,x*2+1);
}

int ans[maxn];
void solve(int x,int par)
{
	for (int i=0;i<op[x].size();i++)
	{
		add(st[op[x][i].F],fn[op[x][i].F],1);
		add(st[op[x][i].S],fn[op[x][i].S],1);
	}
	ans[x]=n-1;
	if (segm[1]==0) ans[x]-=tedm[1];
	for (int i=0;i<v[x].size();i++)
		if (v[x][i]!=par) solve(v[x][i],x);
	for (int i=0;i<op[x].size();i++)
	{
		add(st[op[x][i].F],fn[op[x][i].F],-1);
		add(st[op[x][i].S],fn[op[x][i].S],-1);
	}
}

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

	cin >> n >> m;
	for (int i=0;i<n-1;i++)
	{
		int x,y;
		cin >> x >> y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(1,0);

	for (int i=0;i<m;i++)
	{
		int x,y;
		cin >> x >> y;
		op[x].push_back(mp(x,y));
		op[y].push_back(mp(x,y));
	}
	make_tree();
	solve(1,0);

	for (int i=1;i<=n;i++) cout << max(0,ans[i]) << " ";
	cout << endl;
}


#include <bits/stdc++.h>
using namespace std;
#define mp make_pair
#define F first
#define S second
const int maxn=100010;

int n,m;
vector <int> v[maxn];
int st[maxn],fn[maxn];
vector <pair<int,int> > op[maxn];
int cnt;

void dfs(int x,int par)
{
	st[x]=cnt; cnt++;
	for (int i=0;i<v[x].size();i++)
		if (v[x][i]!=par) dfs(v[x][i],x);
	fn[x]=cnt;
}

int tedm[maxn*4],segm[maxn*4];

void add(int ql,int qr,int val,int l=0,int r=n,int x=1)
{
	if (ql<=l && r<=qr)
	{
		segm[x]+=val;
		return;
	}
	int mid=(l+r)/2;
	if (ql<mid) add(ql,qr,val,l,mid,x*2+0);
	if (qr>mid) add(ql,qr,val,mid,r,x*2+1);
	segm[x]=min(segm[x*2],segm[x*2+1]);
	tedm[x]=0;
	if (segm[x*2]==segm[x])   tedm[x]+=tedm[x*2];
	if (segm[x*2+1]==segm[x]) tedm[x]+=tedm[x*2+1];
}
void make_tree(int l=0,int r=n,int x=1)
{
	tedm[x]=r-l;
	if (r-l<2) return;
	int mid=(l+r)/2;
	make_tree(l,mid,x*2);
	make_tree(mid,r,x*2+1);
}

int ans[maxn];
void solve(int x,int par)
{
	for (int i=0;i<op[x].size();i++)
	{
		add(st[op[x][i].F],fn[op[x][i].F],1);
		add(st[op[x][i].S],fn[op[x][i].S],1);
	}
	ans[x]=n-1;
	if (segm[1]==0) ans[x]-=tedm[1];
	for (int i=0;i<v[x].size();i++)
		if (v[x][i]!=par) solve(v[x][i],x);
	for (int i=0;i<op[x].size();i++)
	{
		add(st[op[x][i].F],fn[op[x][i].F],-1);
		add(st[op[x][i].S],fn[op[x][i].S],-1);
	}
}

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

	cin >> n >> m;
	for (int i=0;i<n-1;i++)
	{
		int x,y;
		cin >> x >> y;
		v[x].push_back(y);
		v[y].push_back(x);
	}
	dfs(1,0);

	for (int i=0;i<m;i++)
	{
		int x,y;
		cin >> x >> y;
		op[x].push_back(mp(x,y));
		op[y].push_back(mp(x,y));
	}
	make_tree();
	solve(1,0);

	for (int i=1;i<=n;i++) cout << max(0,ans[i]) << " ";
	cout << endl;
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

const int N = 123456;

int cnt;
int tn, tin[N], tout[N], answer[N], cover[N << 3], seg[N << 3];
vector<int> adj[N];
vector<pair<int, int>> queries[N];

int query(int id, int f, int t, int qf, int qt) {
    if (seg[id] > 0) return min(qt, t) - max(qf, f) + 1;
    if (qf <= f && t <= qt) return cover[id];
    int m = (f + t) / 2;
    if (qt < m + 1) return query(id << 1, f, m, qf, qt);
    if (qf > m) return query(id << 1 | 1, m + 1, t, qf, qt);
    return query(id << 1, f, m, qf, qt) + query(id << 1 | 1, m + 1, t, qf, qt);
}

void update(int id, int f, int t, int qf, int qt, int v) {
    if (qf <= f && t <= qt) {
        seg[id] += v;
    } else {
        int m = (f + t) / 2;
        if (qf < m + 1) update(id << 1, f, m, qf, qt, v);
        if (qt > m) update(id << 1 | 1, m + 1, t, qf, qt, v);
    }
    if (seg[id] > 0) {
        cover[id] = t - f + 1;
    } else if (f > t) {
        cover[id] = cover[id << 1] + cover[id << 1 | 1];
    } else {
        cover[id] = 0;
    }
}

void dfs(int u, int p) {
    tin[u] = ++tn;
    for (int v : adj[u])
        if (v != p)
            dfs(v, u);
    tout[u] = ++tn;
}

void add(int f, int t) {
    int v = query(1, 1, tn, f, t);
    cnt += (t - f + 1) - v;
    update(1, 1, tn, f, t, 1);
}

void rem(int f, int t) {
    update(1, 1, tn, f, t, -1);
    int v = query(1, 1, tn, f, t);
    cnt -= (t - f + 1) - v;
}

void dfs_solve(int u, int p) {
    int old = cnt;
    for (auto q : queries[u]) {
        add(tin[q.first], tout[q.first]);
        add(tin[q.second], tout[q.second]);
    }
    if (cnt > 0) {
        answer[u] = cnt / 2 - 1;
    }
    for (int v : adj[u])
        if (v != p)
            dfs_solve(v, u);
    for (auto q : queries[u]) {
        rem(tin[q.first], tout[q.first]);
        rem(tin[q.second], tout[q.second]);
    }
}

int main() {
//    freopen("in", "r", stdin);
//    freopen("out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(1, 0);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        queries[u].push_back(make_pair(u, v));
        queries[v].push_back(make_pair(u, v));
    }
    dfs_solve(1, 0);
    for (int i = 1; i <= n; ++i) {
        cout << answer[i] << ' ';
    }
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

const int N = 123456;

int cnt;
int tn, tin[N], tout[N], answer[N], cover[N << 3], seg[N << 3];
vector<int> adj[N];
vector<pair<int, int>> queries[N];

int query(int id, int f, int t, int qf, int qt) {
    if (qf <= f && t <= qt) return cover[id];
    int m = (f + t) / 2;
    if (qt < m + 1) return query(id << 1, f, m, qf, qt);
    if (qf > m) return query(id << 1 | 1, m + 1, t, qf, qt);
    return query(id << 1, f, m, qf, qt) + query(id << 1 | 1, m + 1, t, qf, qt);
}

void update(int id, int f, int t, int qf, int qt, int v) {
    if (qf <= f && t <= qt) {
        seg[id] += v;
    } else {
        int m = (f + t) / 2;
        if (qf < m + 1) update(id << 1, f, m, qf, qt, v);
        if (qt > m) update(id << 1 | 1, m + 1, t, qf, qt, v);
    }
    if (seg[id] > 0) {
        cover[id] = t - f + 1;
    } else if (f > t) {
        cover[id] = cover[id << 1] + cover[id << 1 | 1];
    } else {
        cover[id] = 0;
    }
}

void dfs(int u, int p) {
    tin[u] = ++tn;
    for (int v : adj[u])
        if (v != p)
            dfs(v, u);
    tout[u] = ++tn;
}

void add(int f, int t) {
    int v = query(1, 1, tn, f, t);
    cnt += (t - f + 1) - v;
    update(1, 1, tn, f, t, 1);
}

void rem(int f, int t) {
    update(1, 1, tn, f, t, -1);
    int v = query(1, 1, tn, f, t);
    cnt -= (t - f + 1) - v;
}

void dfs_solve(int u, int p) {
    int old = cnt;
    for (auto q : queries[u]) {
        add(tin[q.first], tout[q.first]);
        add(tin[q.second], tout[q.second]);
    }
    if (cnt > 0) {
        answer[u] = cnt / 2 - 1;
    }
    for (int v : adj[u])
        if (v != p)
            dfs_solve(v, u);
    for (auto q : queries[u]) {
        rem(tin[q.first], tout[q.first]);
        rem(tin[q.second], tout[q.second]);
    }
}

int main() {
//    freopen("in", "r", stdin);
//    freopen("out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(1, 0);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        queries[u].push_back(make_pair(u, v));
        queries[v].push_back(make_pair(u, v));
    }
    dfs_solve(1, 0);
    for (int i = 1; i <= n; ++i) {
        cout << answer[i] << ' ';
    }
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

const int N = 123456;

int cnt;
int tn, tin[N], tout[N], answer[N], cover[N << 3], seg[N << 3];
vector<int> adj[N];
vector<pair<int, int>> queries[N];

int query(int id, int f, int t, int qf, int qt) {
    if (seg[id] > 0) return min(qt, t) - max(qf, f) + 1;
    if (qf <= f && t <= qt) return cover[id];
    int m = (f + t) / 2;
    if (qt < m + 1) return query(id << 1, f, m, qf, qt);
    if (qf > m) return query(id << 1 | 1, m + 1, t, qf, qt);
    return query(id << 1, f, m, qf, qt) + query(id << 1 | 1, m + 1, t, qf, qt);
}

void update(int id, int f, int t, int qf, int qt, int v) {
    if (qf <= f && t <= qt) {
        seg[id] += v;
    } else {
        int m = (f + t) / 2;
        if (qf < m + 1) update(id << 1, f, m, qf, qt, v);
        if (qt > m) update(id << 1 | 1, m + 1, t, qf, qt, v);
    }
    if (seg[id] > 0) {
        cover[id] = t - f + 1;
    } else if (f < t) {
        cover[id] = cover[id << 1] + cover[id << 1 | 1];
    } else {
        cover[id] = 0;
    }
}

void dfs(int u, int p) {
    tin[u] = ++tn;
    for (int v : adj[u])
        if (v != p)
            dfs(v, u);
    tout[u] = ++tn;
}

void add(int f, int t) {
    int v = query(1, 1, tn, f, t);
    cnt += (t - f + 1) - v;
    update(1, 1, tn, f, t, 1);
}

void rem(int f, int t) {
    update(1, 1, tn, f, t, -1);
    int v = query(1, 1, tn, f, t);
    cnt -= (t - f + 1) - v;
}

void dfs_solve(int u, int p) {
    int old = cnt;
    for (auto q : queries[u]) {
        add(tin[q.first], tout[q.first]);
        add(tin[q.second], tout[q.second]);
    }
    if (cnt > 0) {
        answer[u] = cnt / 2 - 1;
    }
    for (int v : adj[u])
        if (v != p)
            dfs_solve(v, u);
    for (auto q : queries[u]) {
        rem(tin[q.first], tout[q.first]);
        rem(tin[q.second], tout[q.second]);
    }
}

int main() {
//    freopen("in", "r", stdin);
//    freopen("out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(1, 0);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        queries[u].push_back(make_pair(u, v));
        queries[v].push_back(make_pair(u, v));
    }
    dfs_solve(1, 0);
    for (int i = 1; i <= n; ++i) {
        cout << answer[i] << ' ';
    }
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

const int N = 123456;

int cnt;
int tn, tin[N], tout[N], answer[N], cover[N << 2], seg[N << 2];
vector<int> adj[N];
vector<pair<int, int>> queries[N];

void update(int id, int f, int t, int qf, int qt, int v) {
    if (qf <= f && t <= qt) {
        seg[id] += v;
    } else {
        int m = (f + t) / 2;
        if (qf < m + 1) update(id << 1, f, m, qf, qt, v);
        if (qt > m) update(id << 1 | 1, m + 1, t, qf, qt, v);
    }
    if (seg[id] > 0) {
        cover[id] = t - f + 1;
    } else if (f < t) {
        cover[id] = cover[id << 1] + cover[id << 1 | 1];
    } else {
        cover[id] = 0;
    }
}

void dfs(int u, int p) {
    tin[u] = ++tn;
    for (int v : adj[u])
        if (v != p)
            dfs(v, u);
    tout[u] = tn;
}

void add(int f, int t) {
    update(1, 1, tn, f, t, 1);
}

void rem(int f, int t) {
    update(1, 1, tn, f, t, -1);
}

void dfs_solve(int u, int p) {
    for (auto q : queries[u]) {
        add(tin[q.first], tout[q.first]);
        add(tin[q.second], tout[q.second]);
    }
    if (cover[1] > 0) {
        answer[u] = cover[1] - 1;
    }
    for (int v : adj[u])
        if (v != p)
            dfs_solve(v, u);
    for (auto q : queries[u]) {
        rem(tin[q.first], tout[q.first]);
        rem(tin[q.second], tout[q.second]);
    }
}

int main() {
//    freopen("in", "r", stdin);
//    freopen("out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(1, 0);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        queries[u].push_back(make_pair(u, v));
        queries[v].push_back(make_pair(u, v));
    }
    dfs_solve(1, 0);
    for (int i = 1; i <= n; ++i) {
        cout << answer[i] << ' ';
    }
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

const int N = 123456;

int cnt;
int tn, tin[N], tout[N], answer[N], cover[N << 3], seg[N << 3];
vector<int> adj[N];
vector<pair<int, int>> queries[N];

int query(int id, int f, int t, int qf, int qt) {
    if (seg[id] > 0) return min(qt, t) - max(qf, f) + 1;
    if (f == t) return cover[id];
    int m = (f + t) / 2;
    if (qt < m + 1) return query(id << 1, f, m, qf, qt);
    if (qf > m) return query(id << 1 | 1, m + 1, t, qf, qt);
    return query(id << 1, f, m, qf, qt) + query(id << 1 | 1, m + 1, t, qf, qt);
}

void update(int id, int f, int t, int qf, int qt, int v) {
    if (qf <= f && t <= qt) {
        seg[id] += v;
    } else {
        int m = (f + t) / 2;
        if (qf < m + 1) update(id << 1, f, m, qf, qt, v);
        if (qt > m) update(id << 1 | 1, m + 1, t, qf, qt, v);
    }
    if (seg[id] > 0) {
        cover[id] = t - f + 1;
    } else if (f > t) {
        cover[id] = cover[id << 1] + cover[id << 1 | 1];
    } else {
        cover[id] = 0;
    }
}

void dfs(int u, int p) {
    tin[u] = ++tn;
    for (int v : adj[u])
        if (v != p)
            dfs(v, u);
    tout[u] = ++tn;
}

void add(int f, int t) {
    int v = query(1, 1, tn, f, t);
    cnt += (t - f + 1) - v;
    update(1, 1, tn, f, t, 1);
}

void rem(int f, int t) {
    update(1, 1, tn, f, t, -1);
    int v = query(1, 1, tn, f, t);
    cnt -= (t - f + 1) - v;
}

void dfs_solve(int u, int p) {
    int old = cnt;
    for (auto q : queries[u]) {
        add(tin[q.first], tout[q.first]);
        add(tin[q.second], tout[q.second]);
    }
    if (cnt > 0) {
        answer[u] = cnt / 2 - 1;
    }
    for (int v : adj[u])
        if (v != p)
            dfs_solve(v, u);
    for (auto q : queries[u]) {
        rem(tin[q.first], tout[q.first]);
        rem(tin[q.second], tout[q.second]);
    }
}

int main() {
//    freopen("in", "r", stdin);
//    freopen("out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(1, 0);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        queries[u].push_back(make_pair(u, v));
        queries[v].push_back(make_pair(u, v));
    }
    dfs_solve(1, 0);
    for (int i = 1; i <= n; ++i) {
        cout << answer[i] << ' ';
    }
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>

using namespace std;

const int N = 123456;

int cnt;
int tn, tin[N], tout[N], answer[N], cover[N << 2], seg[N << 2];
vector<int> adj[N];
vector<pair<int, int>> queries[N];

int query(int id, int f, int t, int qf, int qt) {
    if (seg[id] > 0) return min(qt, t) - max(qf, f) + 1;
    if (qf <= f && t <= qt) return cover[id];
    int m = (f + t) / 2;
    if (qt < m + 1) return query(id << 1, f, m, qf, qt);
    if (qf > m) return query(id << 1 | 1, m + 1, t, qf, qt);
    return query(id << 1, f, m, qf, qt) + query(id << 1 | 1, m + 1, t, qf, qt);
}

void update(int id, int f, int t, int qf, int qt, int v) {
    if (qf <= f && t <= qt) {
        seg[id] += v;
    } else {
        int m = (f + t) / 2;
        if (qf < m + 1) update(id << 1, f, m, qf, qt, v);
        if (qt > m) update(id << 1 | 1, m + 1, t, qf, qt, v);
    }
    if (seg[id] > 0) {
        cover[id] = t - f + 1;
    } else if (f < t) {
        cover[id] = cover[id << 1] + cover[id << 1 | 1];
    } else {
        cover[id] = 0;
    }
}

void dfs(int u, int p) {
    tin[u] = ++tn;
    for (int v : adj[u])
        if (v != p)
            dfs(v, u);
    tout[u] = tn;
}

void add(int f, int t) {
    int v = query(1, 1, tn, f, t);
    cnt += (t - f + 1) - v;
    update(1, 1, tn, f, t, 1);
}

void rem(int f, int t) {
    update(1, 1, tn, f, t, -1);
    int v = query(1, 1, tn, f, t);
    cnt -= (t - f + 1) - v;
}

void dfs_solve(int u, int p) {
    int old = cnt;
    for (auto q : queries[u]) {
        add(tin[q.first], tout[q.first]);
        add(tin[q.second], tout[q.second]);
    }
    if (cnt > 0) {
        answer[u] = cnt - 1;
    }
    for (int v : adj[u])
        if (v != p)
            dfs_solve(v, u);
    for (auto q : queries[u]) {
        rem(tin[q.first], tout[q.first]);
        rem(tin[q.second], tout[q.second]);
    }
}

int main() {
//    freopen("in", "r", stdin);
//    freopen("out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n, m;
    cin >> n >> m;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(1, 0);
    for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        queries[u].push_back(make_pair(u, v));
        queries[v].push_back(make_pair(u, v));
    }
    dfs_solve(1, 0);
    for (int i = 1; i <= n; ++i) {
        cout << answer[i] << ' ';
    }
}


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Vector;

public class solve {
	static PrintWriter out = new PrintWriter(System.out);
	static Scanner sc = new Scanner(System.in);
	static int n, m, b, mod ;
	static int a[];
	static int dp[][][];

	public static void main(String[] args) throws Exception {
		n =sc.nextInt();
		m=sc.nextInt();
		b=sc.nextInt();
		mod=sc.nextInt();
		 a=new int[n];
		dp=new int[n+1+4][m+1+4][b+4];;

		for(int i=0;i<n;i++)
			a[i]=sc.nextInt();
		for(int i=0;i<dp.length;i++)
			for(int j=0;j<dp[i].length;j++)
				for(int k=0;k<dp[i][j].length;k++)
					dp[i][j][k]=-1;

		out.println(solve(0,b,0));
		out.close();

	}

	public static int solve(int idx,int s,int u) {
		if(s<0)
			return 0;
		if(idx==n) {
			if(s>=0)
				if(u==m)
				return 1;
			else
				return 0;
		}
		if(dp[idx][s][u]!=-1)
			return dp[idx][s][u];

		int c1 = solve(idx,s-a[idx],u+1)%mod;
		int c2 = solve(idx+1,s,u)%mod;
		return dp[idx][s][u]=(c1%mod+c2%mod)%mod;

	}

}

class Point{
	int x ;
	int y ;

	public Point(int x,int y) {
		this.x=x;
		this.y=y;
	}

	void print() {
		System.out.println(x+" "+y);
	}

	double slope() {
		return (double)y/x*1.0;
	}

}

class pair implements Comparable{
	int x ,y,z;
	pair(int x,int y,int z)
	{
		this.x=x;
		this.y=y;
		this.z=z;
	}
	@Override
	public int compareTo(Object arg0) {

		pair u =((pair)arg0);

		return -this.z+u.z;
	}
}

class Scanner {
	StringTokenizer st;
	BufferedReader br;

	public Scanner(InputStream s) {
		br = new BufferedReader(new InputStreamReader(s));
	}

	public Scanner(String f) throws FileNotFoundException {
		br = new BufferedReader(new FileReader(f));
	}

	public String next() throws IOException {
		while (st == null || !st.hasMoreTokens())
			st = new StringTokenizer(br.readLine());
		return st.nextToken();
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public String nextLine() throws IOException {
		return br.readLine();
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	public boolean ready() throws IOException {
		return br.ready();
	}

	public int[] nextIntArray(int n) throws IOException {
		int[] a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = nextInt();
		return a;
	}

	public int[] nextIntArray1(int n) throws IOException {
		int[] a = new int[n + 1];
		for (int i = 1; i <= n; i++)
			a[i] = nextInt();
		return a;
	}

	public int[] shuffle(int[] a, int n) {
		int[] b = new int[n];
		for (int i = 0; i < n; i++)
			b[i] = a[i];
		Random r = new Random();
		for (int i = 0; i < n; i++) {
			int j = i + r.nextInt(n - i);
			int t = b[i];
			b[i] = b[j];
			b[j] = t;
		}
		return b;
	}

	public int[] nextIntArraySorted(int n) throws IOException {
		int[] a = nextIntArray(n);
		a = shuffle(a, n);
		Arrays.sort(a);
		return a;
	}

	public long[] nextLongArray(int n) throws IOException {
		long[] a = new long[n];
		for (int i = 0; i < n; i++)
			a[i] = nextLong();
		return a;
	}

	public long[] nextLongArray1(int n) throws IOException {
		long[] a = new long[n + 1];
		for (int i = 1; i <= n; i++)
			a[i] = nextLong();
		return a;
	}

	public long[] nextLongArraySorted(int n) throws IOException {
		long[] a = nextLongArray(n);
		Random r = new Random();
		for (int i = 0; i < n; i++) {
			int j = i + r.nextInt(n - i);
			long t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
		Arrays.sort(a);
		return a;
	}
}


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Vector;

public class solve {
	static PrintWriter out = new PrintWriter(System.out);
	static Scanner sc = new Scanner(System.in);
	static int n, m, b, mod ;
	static int a[];
	static int dp[][][];

	public static void main(String[] args) throws Exception {
		dp=new int[500][500][500];;
		n =sc.nextInt();
		m=sc.nextInt();
		b=sc.nextInt();
		mod=sc.nextInt();
		 a=new int[n];
		for(int i=0;i<n;i++)
			a[i]=sc.nextInt();
		for(int i=0;i<dp.length;i++)
			for(int j=0;j<dp[i].length;j++)
				for(int k=0;k<dp[i][j].length;k++)
					dp[i][j][k]=-1;

		out.println(solve(0,0,0));
		out.close();

	}

	public static int solve(int idx,int s,int u) {
		if(s>b)
			return 0;
		if(idx==n) {
			if(s<=b)
				if(u==m)
				return 1;
			else
				return 0;
		}
		if(dp[idx][s][u]!=-1)
			return dp[idx][s][u];

		int c1 = solve(idx,s+a[idx],u+1)%mod;
		int c2 = solve(idx+1,s,u)%mod;
		return dp[idx][s][u]=(c1%mod+c2%mod)%mod;

	}

}

class Point{
	int x ;
	int y ;

	public Point(int x,int y) {
		this.x=x;
		this.y=y;
	}

	void print() {
		System.out.println(x+" "+y);
	}

	double slope() {
		return (double)y/x*1.0;
	}

}

class pair implements Comparable{
	int x ,y,z;
	pair(int x,int y,int z)
	{
		this.x=x;
		this.y=y;
		this.z=z;
	}
	@Override
	public int compareTo(Object arg0) {

		pair u =((pair)arg0);

		return -this.z+u.z;
	}
}

class Scanner {
	StringTokenizer st;
	BufferedReader br;

	public Scanner(InputStream s) {
		br = new BufferedReader(new InputStreamReader(s));
	}

	public Scanner(String f) throws FileNotFoundException {
		br = new BufferedReader(new FileReader(f));
	}

	public String next() throws IOException {
		while (st == null || !st.hasMoreTokens())
			st = new StringTokenizer(br.readLine());
		return st.nextToken();
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public String nextLine() throws IOException {
		return br.readLine();
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	public boolean ready() throws IOException {
		return br.ready();
	}

	public int[] nextIntArray(int n) throws IOException {
		int[] a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = nextInt();
		return a;
	}

	public int[] nextIntArray1(int n) throws IOException {
		int[] a = new int[n + 1];
		for (int i = 1; i <= n; i++)
			a[i] = nextInt();
		return a;
	}

	public int[] shuffle(int[] a, int n) {
		int[] b = new int[n];
		for (int i = 0; i < n; i++)
			b[i] = a[i];
		Random r = new Random();
		for (int i = 0; i < n; i++) {
			int j = i + r.nextInt(n - i);
			int t = b[i];
			b[i] = b[j];
			b[j] = t;
		}
		return b;
	}

	public int[] nextIntArraySorted(int n) throws IOException {
		int[] a = nextIntArray(n);
		a = shuffle(a, n);
		Arrays.sort(a);
		return a;
	}

	public long[] nextLongArray(int n) throws IOException {
		long[] a = new long[n];
		for (int i = 0; i < n; i++)
			a[i] = nextLong();
		return a;
	}

	public long[] nextLongArray1(int n) throws IOException {
		long[] a = new long[n + 1];
		for (int i = 1; i <= n; i++)
			a[i] = nextLong();
		return a;
	}

	public long[] nextLongArraySorted(int n) throws IOException {
		long[] a = nextLongArray(n);
		Random r = new Random();
		for (int i = 0; i < n; i++) {
			int j = i + r.nextInt(n - i);
			long t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
		Arrays.sort(a);
		return a;
	}
}


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Vector;

public class solve {
	static PrintWriter out = new PrintWriter(System.out);
	static Scanner sc = new Scanner(System.in);

	public static void main(String[] args) throws Exception {
		 int n, m, b, mod ;
		 int a[];
		 int dp[][][];

		n =sc.nextInt();
		m=sc.nextInt();
		b=sc.nextInt();
		mod=sc.nextInt();
		 a=new int[n];
		dp=new int[2][m+1][b+1];;

		for(int i=0;i<n;i++)
			a[i]=sc.nextInt();
		// 0 previous
		// 1 current
		// dp[i][j][k] number if ways to write j lines with at most k bugs till index i
		// dp[1][j][k]=dp[0][j][k]+d
		Arrays.fill(dp[0][0], 1);
		Arrays.fill(dp[1][0], 1);

		for(int i=0;i<n;i++) {
			dp[1]=new int[m+1][b+1];;
			for(int y=0;y<dp[1].length;y++)
				if(y==0)
				Arrays.fill(dp[1][y], 1);
				else
					Arrays.fill(dp[1][y], 0);

			for(int j=1;j<=m;j++) {
				for(int k=0;k<=b;k++) {
					dp[1][j][k]=dp[0][j][k]%mod;
					if(k-a[i]>=0){
						dp[1][j][k]+=dp[1][j-1][k-a[i]]%mod;
					};
					dp[1][j][k]%=mod;
				}
			}

			dp[0]=dp[1];
		}
		System.out.println(dp[0][m][b]%mod);

	}

}

class Point{
	int x ;
	int y ;

	public Point(int x,int y) {
		this.x=x;
		this.y=y;
	}

	void print() {
		System.out.println(x+" "+y);
	}

	double slope() {
		return (double)y/x*1.0;
	}

}

class pair implements Comparable{
	int x ,y,z;
	pair(int x,int y,int z)
	{
		this.x=x;
		this.y=y;
		this.z=z;
	}
	@Override
	public int compareTo(Object arg0) {

		pair u =((pair)arg0);

		return -this.z+u.z;
	}
}

class Scanner {
	StringTokenizer st;
	BufferedReader br;

	public Scanner(InputStream s) {
		br = new BufferedReader(new InputStreamReader(s));
	}

	public Scanner(String f) throws FileNotFoundException {
		br = new BufferedReader(new FileReader(f));
	}

	public String next() throws IOException {
		while (st == null || !st.hasMoreTokens())
			st = new StringTokenizer(br.readLine());
		return st.nextToken();
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public String nextLine() throws IOException {
		return br.readLine();
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	public boolean ready() throws IOException {
		return br.ready();
	}

	public int[] nextIntArray(int n) throws IOException {
		int[] a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = nextInt();
		return a;
	}

	public int[] nextIntArray1(int n) throws IOException {
		int[] a = new int[n + 1];
		for (int i = 1; i <= n; i++)
			a[i] = nextInt();
		return a;
	}

	public int[] shuffle(int[] a, int n) {
		int[] b = new int[n];
		for (int i = 0; i < n; i++)
			b[i] = a[i];
		Random r = new Random();
		for (int i = 0; i < n; i++) {
			int j = i + r.nextInt(n - i);
			int t = b[i];
			b[i] = b[j];
			b[j] = t;
		}
		return b;
	}

	public int[] nextIntArraySorted(int n) throws IOException {
		int[] a = nextIntArray(n);
		a = shuffle(a, n);
		Arrays.sort(a);
		return a;
	}

	public long[] nextLongArray(int n) throws IOException {
		long[] a = new long[n];
		for (int i = 0; i < n; i++)
			a[i] = nextLong();
		return a;
	}

	public long[] nextLongArray1(int n) throws IOException {
		long[] a = new long[n + 1];
		for (int i = 1; i <= n; i++)
			a[i] = nextLong();
		return a;
	}

	public long[] nextLongArraySorted(int n) throws IOException {
		long[] a = nextLongArray(n);
		Random r = new Random();
		for (int i = 0; i < n; i++) {
			int j = i + r.nextInt(n - i);
			long t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
		Arrays.sort(a);
		return a;
	}
}


import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.Vector;

  public class solve {
	static PrintWriter out = new PrintWriter(System.out);
	static Scanner sc = new Scanner(System.in);
	static int n, m, b, mod ;
	static int a[];
	static int dp[][][]=new int[500+2][500+2][500+2];

	public static void main(String[] args) throws NumberFormatException, IOException {

		n =sc.nextInt();
		m=sc.nextInt();
		b=sc.nextInt();
		mod=sc.nextInt();
		 a=new int[n];
		for(int i=0;i<n;i++)
			a[i]=sc.nextInt();
		for(int i=0;i<dp.length;i++)
			for(int j=0;j<dp[i].length;j++)
				for(int k=0;k<dp[i][j].length;k++)
					dp[i][j][k]=-1;

		System.out.println(solve(0,0,0));

	}

	public static int solve(int idx,int s,int u) {
		if(s>b)
			return 0;
		if(idx==n) {
			if(s<=b)
				if(u==m)
				return 1;
			else
				return 0;
		}
		if(dp[idx][s][u]!=-1)
			return dp[idx][s][u];

		int c1 = solve(idx,s+a[idx],u+1)%mod;
		int c2 = solve(idx+1,s,u)%mod;
		return dp[idx][s][u]=(c1%mod+c2%mod)%mod;

	}

	}

class Point{
	int x ;
	int y ;

	public Point(int x,int y) {
		this.x=x;
		this.y=y;
	}

	void print() {
		System.out.println(x+" "+y);
	}

	double slope() {
		return (double)y/x*1.0;
	}

}

class pair implements Comparable{
	int x ,y,z;
	pair(int x,int y,int z)
	{
		this.x=x;
		this.y=y;
		this.z=z;
	}
	@Override
	public int compareTo(Object arg0) {

		pair u =((pair)arg0);

		return -this.z+u.z;
	}
}

class Scanner {
	StringTokenizer st;
	BufferedReader br;

	public Scanner(InputStream s) {
		br = new BufferedReader(new InputStreamReader(s));
	}

	public Scanner(String f) throws FileNotFoundException {
		br = new BufferedReader(new FileReader(f));
	}

	public String next() throws IOException {
		while (st == null || !st.hasMoreTokens())
			st = new StringTokenizer(br.readLine());
		return st.nextToken();
	}

	public int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	public long nextLong() throws IOException {
		return Long.parseLong(next());
	}

	public String nextLine() throws IOException {
		return br.readLine();
	}

	public double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	public boolean ready() throws IOException {
		return br.ready();
	}

	public int[] nextIntArray(int n) throws IOException {
		int[] a = new int[n];
		for (int i = 0; i < n; i++)
			a[i] = nextInt();
		return a;
	}

	public int[] nextIntArray1(int n) throws IOException {
		int[] a = new int[n + 1];
		for (int i = 1; i <= n; i++)
			a[i] = nextInt();
		return a;
	}

	public int[] shuffle(int[] a, int n) {
		int[] b = new int[n];
		for (int i = 0; i < n; i++)
			b[i] = a[i];
		Random r = new Random();
		for (int i = 0; i < n; i++) {
			int j = i + r.nextInt(n - i);
			int t = b[i];
			b[i] = b[j];
			b[j] = t;
		}
		return b;
	}

	public int[] nextIntArraySorted(int n) throws IOException {
		int[] a = nextIntArray(n);
		a = shuffle(a, n);
		Arrays.sort(a);
		return a;
	}

	public long[] nextLongArray(int n) throws IOException {
		long[] a = new long[n];
		for (int i = 0; i < n; i++)
			a[i] = nextLong();
		return a;
	}

	public long[] nextLongArray1(int n) throws IOException {
		long[] a = new long[n + 1];
		for (int i = 1; i <= n; i++)
			a[i] = nextLong();
		return a;
	}

	public long[] nextLongArraySorted(int n) throws IOException {
		long[] a = nextLongArray(n);
		Random r = new Random();
		for (int i = 0; i < n; i++) {
			int j = i + r.nextInt(n - i);
			long t = a[i];
			a[i] = a[j];
			a[j] = t;
		}
		Arrays.sort(a);
		return a;
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class A
{
    private static int mod;
    public static void main(String[] args) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer tokenizer = new StringTokenizer(reader.readLine());

        int n = Integer.parseInt(tokenizer.nextToken());
        int m = Integer.parseInt(tokenizer.nextToken());
        int b = Integer.parseInt(tokenizer.nextToken());
        mod = Integer.parseInt(tokenizer.nextToken());

        int [] bugs = new int[n];
        tokenizer = new StringTokenizer(reader.readLine());
        for(int i = 0  ;i < n ; i++)
            bugs[i] = Integer.parseInt(tokenizer.nextToken());

        int [][] curr = new int[m+1][b+1];
        int [][] next = new int[m+1][b+1];
        curr[0][0] = 1%mod;

        for(int i = 0 ; i < n ; i++)
        {
            for(int [] fill : next)
                Arrays.fill(fill, 0);
            for(int j = 0 ; j <= m ; j++)
                for(int s = 0 ; s <= b ; s++)
                    if(curr[j][s] != 0)
                    {
                        next[j][s] += curr[j][s];
                        if(next[j][s] >= mod)
                            next[j][s] -= mod;
                        if(1+j <= m && bugs[i]+s <= b)
                        {
                            curr[1+j][bugs[i]+s] += curr[j][s];
                            if(curr[1+j][bugs[i]+s] >= mod)
                                curr[1+j][bugs[i]+s] -= mod;
                        }
                    }

            for(int v1 = 0 ; v1 < next.length ; v1++)
                for(int v2 = 0  ;v2 < next[v1].length ; v2++)
                    curr[v1][v2] = next[v1][v2];
        }

        long res = 0;
        for(int i = 0 ; i  <= b ; i++)
        {
            res += curr[m][i];
            if(res >= mod)
                res -= mod;
        }
        System.out.println(res);

    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

public class A
{
    private static int mod;
    public static void main(String[] args) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        StringTokenizer tokenizer = new StringTokenizer(reader.readLine());

        int n = Integer.parseInt(tokenizer.nextToken());
        int m = Integer.parseInt(tokenizer.nextToken());
        int b = Integer.parseInt(tokenizer.nextToken());
        mod = Integer.parseInt(tokenizer.nextToken());

        int [] bugs = new int[n];
        tokenizer = new StringTokenizer(reader.readLine());
        for(int i = 0  ;i < n ; i++)
            bugs[i] = Integer.parseInt(tokenizer.nextToken());

        int [][] curr = new int[m+1][b+1];
        int [][] next = new int[m+1][b+1];
        curr[0][0] = 1%mod;

        for(int i = 0 ; i < n ; i++)
        {
            for(int [] fill : next)
                Arrays.fill(fill, 0);
            for(int j = 0 ; j <= m ; j++)
                for(int s = 0 ; s <= b ; s++)
                    if(curr[j][s] != 0)
                        for(int w = 0 ; w+j <= m && w*bugs[i]+s <= b ; w++)
                        {
                            next[w+j][w*bugs[i]+s] += curr[j][s];
                            if(next[w+j][w*bugs[i]+s] >= mod)
                                next[w+j][w*bugs[i]+s] -= mod;
                        }

            for(int v1 = 0 ; v1 < next.length ; v1++)
                for(int v2 = 0  ;v2 < next[v1].length ; v2++)
                    curr[v1][v2] = next[v1][v2];
        }

        long res = 0;
        for(int i = 0 ; i  <= b ; i++)
        {
            res += curr[m][i];
            if(res >= mod)
                res -= mod;
        }
        System.out.println(res);

    }
}


import java.util.Arrays;
import java.util.Scanner;

public class WritingCode {
	static int [] arr;
	static int [][][] dp;

	static int b;
	static int mod;

	static int solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}
		if ( idx == arr.length) {
			if (rem == 0 && bugs <= b) {
				return 1;
			}
			return 0;
		}
		if (dp [idx][rem][bugs] != -1) {
			return dp[idx][rem][bugs];
		}

		dp[idx][rem][bugs] =  ((solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs ))%mod) ;
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		b = in.nextInt();
		mod = in.nextInt();
		arr = new int[n];
		dp = new int [n][m+1][b+1];
		for (int i = 0; i < n; i++) {
			arr[i] = in.nextInt();
		}
		for (int i = 0; i < dp.length; i++) {
			for (int j = 0; j < dp[0].length; j++) {
				for (int j2 = 0; j2 < dp[0][0].length; j2++) {
					dp[i][j][j2] = -1;
				}
			}
		}

		System.out.println(solve(0, m, 0));
	}

}


import java.util.Arrays;
import java.util.Scanner;

public class WritingCode {
	static int [] arr;
	static int [][][] dp;

	static int b;
	static int mod;

	static int solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}

			if (rem == 0 ) {
				return 1;
			}
			if(idx == arr.length )return 0;
		if (dp [idx][rem][bugs] != -1) {
			return dp[idx][rem][bugs];
		}

		dp[idx][rem][bugs] =  ((solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs ))%mod);
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		b = in.nextInt();
		mod = in.nextInt();
		arr = new int[n + 1];
		dp = new int [2][b+1][m+1];
		for (int i = 1; i < n + 1; i++) {
			arr[i] = in.nextInt();
		}
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < b + 1; j++) {
				dp[i][j][0] = 1;
			}
		}
		int turn = 0;
		for (int i = 1; i < n+1; i++) {
			turn = (turn + 1)%2;
			for (int j = 0; j < b+1; j++) {
				for (int j2 = 1; j2 < m+1; j2++) {
					dp [turn][j][j2] = dp[(turn + 1)%2][j][j2];
					if (j - arr[i] >= 0) {
						dp [turn][j][j2] +=  dp[turn][j - arr[i]][j2 - 1];
					}

				}

			}
		}
		System.out.println(dp[turn][b][m]);
	}

}


import java.util.Scanner;

public class WritingCode {
	int [] arr;
	int [][][] dp;

	int b;
	int mod;

	public WritingCode(int[] arr, int[][][] dp,  int b, int mod) {
		super();
		this.arr = arr;
		this.dp = dp;
		this.b = b;
		this.mod = mod;
	}
	long solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}
		if ( idx == arr.length) {
			if (rem == 0 && bugs <= b) {
				return 1;
			}
			return 0;
		}
		if (dp [idx][rem][bugs] != 0) {
			return dp[idx][rem][bugs];
		}

		dp[idx][rem][bugs] =  (int) ((solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs ))%mod) ;
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int b = in.nextInt();
		int mod = in.nextInt();
		int [] arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = in.nextInt();
		}
		WritingCode x = new WritingCode(arr, new int [n][m+1][b+1], b,mod);
		System.out.println(x.solve(0, m, 0) % mod);
	}

}


import java.util.Scanner;

public class WritingCode {
	int [] arr;
	long [][][] dp;
	boolean [][][] visited;
	int b;

	public WritingCode(int[] arr, long[][][] dp, boolean[][][] visited, int b) {
		super();
		this.arr = arr;
		this.dp = dp;
		this.visited = visited;
		this.b = b;
	}
	long solve(int idx,int rem,int bugs) {
		if (rem < 0) {
			return 0;
		}
		if ( idx == arr.length) {
			if (rem == 0 && bugs == b) {
				return 1;
			}
			return 0;
		}
		if (visited [idx][rem][bugs]) {
			return dp[idx][rem][bugs];
		}
		visited [idx][rem][bugs] = true;
		dp[idx][rem][bugs] =  solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs  );
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int b = in.nextInt();
		int mod = in.nextInt();
		int [] arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = in.nextInt();
		}
		WritingCode x = new WritingCode(arr, new long [n][m+1][b+1], new boolean[n][m+1][b+1], b);
		System.out.println(x.solve(0, m, 0) % mod);
	}

}


import java.util.Arrays;
import java.util.Scanner;

public class WritingCode {
	static int [] arr;
	static int [][][] dp;

	static int b;
	static int mod;

	static int solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}

			if (rem == 0 ) {
				return 1;
			}
			if(idx == arr.length )return 0;
		if (dp [idx][rem][bugs] != -1) {
			return dp[idx][rem][bugs];
		}

		dp[idx][rem][bugs] =  ((solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs ))%mod);
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		b = in.nextInt();
		mod = in.nextInt();
		arr = new int[n + 1];
		dp = new int [2][b+1][m+1];
		for (int i = 1; i < n + 1; i++) {
			arr[i] = in.nextInt();
		}
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < b + 1; j++) {
				dp[i][j][0] = 1;
			}
		}
		int turn = 0;
		for (int i = 1; i < n+1; i++) {
			turn = (turn + 1)%2;
			for (int j = 0; j < b+1; j++) {
				for (int j2 = 1; j2 < m+1; j2++) {
					dp [turn][j][j2] = dp[(turn + 1)%2][j][j2] % mod;
					if (j - arr[i] >= 0) {
						dp [turn][j][j2] =(dp [turn][j][j2] +  dp[turn][j - arr[i]][j2 - 1])% mod;
					}

				}

			}
		}
		System.out.println(dp[turn][b][m]);
	}

}


import java.util.Scanner;

public class WritingCode {
	int [] arr;
	int [][] dp;
	boolean [][] visited;
	int b;
	int mod;

	public WritingCode(int[] arr, int[][] dp, boolean[][] visited, int b, int mod) {
		super();
		this.arr = arr;
		this.dp = dp;
		this.visited = visited;
		this.b = b;
		this.mod = mod;
	}
	long solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}
		if ( idx == arr.length) {
			if (rem == 0 && bugs <= b) {
				return 1;
			}
			return 0;
		}
		if (visited [idx][rem]) {
			return dp[idx][rem];
		}
		visited [idx][rem] = true;
		dp[idx][rem] =   (int) ((solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs  )) % mod) ;
		return dp[idx][rem];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int b = in.nextInt();
		int mod = in.nextInt();
		int [] arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = in.nextInt();
		}
		WritingCode x = new WritingCode(arr, new int [n][m + 1], new boolean [n][m+1], b, mod);
		System.out.println(x.solve(0, m, 0) % mod);
	}

}


import java.util.Scanner;

public class WritingCode {
	int [] arr;
	long [][][] dp;
	boolean [][][] visited;
	int b;

	public WritingCode(int[] arr, long[][][] dp, boolean[][][] visited, int b) {
		super();
		this.arr = arr;
		this.dp = dp;
		this.visited = visited;
		this.b = b;
	}
	long solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}
		if ( idx == arr.length) {
			if (rem == 0 && bugs <= b) {
				return 1;
			}
			return 0;
		}
		if (visited [idx][rem][bugs]) {
			return dp[idx][rem][bugs];
		}
		visited [idx][rem][bugs] = true;
		dp[idx][rem][bugs] =  solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs  );
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int b = in.nextInt();
		int mod = in.nextInt();
		int [] arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = in.nextInt();
		}
		WritingCode x = new WritingCode(arr, new long [n][m+1][b+1], new boolean[n][m+1][b+1], b);
		System.out.println(x.solve(0, m, 0) % mod);
	}

}


import java.util.Scanner;

public class WritingCode {
	int [] arr;
	long [][][] dp;
	boolean [][][] visited;
	int b;

	public WritingCode(int[] arr, long[][][] dp, boolean[][][] visited, int b) {
		super();
		this.arr = arr;
		this.dp = dp;
		this.visited = visited;
		this.b = b;
	}
	long solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}
		if ( idx == arr.length) {
			if (rem == 0 && bugs >= b) {
				return 1;
			}
			return 0;
		}
		if (visited [idx][rem][bugs]) {
			return dp[idx][rem][bugs];
		}
		visited [idx][rem][bugs] = true;
		dp[idx][rem][bugs] =  solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs  );
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int b = in.nextInt();
		int mod = in.nextInt();
		int [] arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = in.nextInt();
		}
		WritingCode x = new WritingCode(arr, new long [n][m+1][b+1], new boolean[n][m+1][b+1], b);
		System.out.println(x.solve(0, m, 0) % mod);
	}

}


import java.util.Arrays;
import java.util.Scanner;

public class WritingCode {
	static int [] arr;
	static int [][][] dp;

	static int b;
	static int mod;

	static int solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}

			if (rem == 0 ) {
				return 1;
			}
			if(idx == arr.length )return 0;
		if (dp [idx][rem][bugs] != -1) {
			return dp[idx][rem][bugs];
		}

		dp[idx][rem][bugs] =  ((solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs ))%mod);
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		b = in.nextInt();
		mod = in.nextInt();
		arr = new int[n + 1];
		dp = new int [2][b+1][m+1];
		for (int i = 1; i < n + 1; i++) {
			arr[i] = in.nextInt();
		}
		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < dp[0][0].length; j++) {
				dp[i][j][0] = 1;
			}
		}
		int turn = 0;
		for (int i = 1; i < n+1; i++) {
			turn = (turn + 1)%2;
			for (int j = 0; j < b+1; j++) {
				for (int j2 = 1; j2 < m+1; j2++) {
					dp [turn][j][j2] = dp[(turn + 1)%2][j][j2];
					if (j - arr[i] >= 0) {
						dp [turn][j][j2] +=  dp[turn][j - arr[i]][j2 - 1];
					}

				}

			}
		}
		System.out.println(dp[turn][b][m]);
	}

}


import java.util.Arrays;
import java.util.Scanner;

public class WritingCode {
	int [] arr;
	int [][][] dp;

	int b;
	int mod;

	public WritingCode(int[] arr, int[][][] dp,  int b, int mod) {
		super();
		this.arr = arr;
		this.dp = dp;
		for (int i = 0; i < dp.length; i++) {
			for (int j = 0; j < dp[0].length; j++) {
				for (int j2 = 0; j2 < dp[0][0].length; j2++) {
					dp[i][j][j2] = -1;
				}
			}
		}
		this.b = b;
		this.mod = mod;
	}
	long solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}
		if ( idx == arr.length) {
			if (rem == 0 && bugs <= b) {
				return 1;
			}
			return 0;
		}
		if (dp [idx][rem][bugs] != -1) {
			return dp[idx][rem][bugs];
		}

		dp[idx][rem][bugs] =  (int) ((solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs ))%mod) ;
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int b = in.nextInt();
		int mod = in.nextInt();
		int [] arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = in.nextInt();
		}
		WritingCode x = new WritingCode(arr, new int [n][m+1][b+1], b,mod);
		System.out.println(x.solve(0, m, 0) % mod);
	}

}


import java.util.Scanner;

public class WritingCode {
	int [] arr;
	int [][][] dp;
	boolean [][][] visited;
	int b;
	int mod;

	public WritingCode(int[] arr, int[][][] dp, boolean[][][] visited, int b, int mod) {
		super();
		this.arr = arr;
		this.dp = dp;
		this.visited = visited;
		this.b = b;
		this.mod = mod;
	}
	long solve(int idx,int rem,int bugs) {
		if (rem < 0 || bugs > b) {
			return 0;
		}
		if ( idx == arr.length) {
			if (rem == 0 && bugs <= b) {
				return 1;
			}
			return 0;
		}
		if (visited [idx][rem][bugs]) {
			return dp[idx][rem][bugs];
		}
		visited [idx][rem][bugs] = true;
		dp[idx][rem][bugs] =  (int) ((solve(idx, rem - 1, bugs + arr[idx]) + solve(idx + 1, rem, bugs ))%mod) ;
		return dp[idx][rem][bugs];
	}
	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		int m = in.nextInt();
		int b = in.nextInt();
		int mod = in.nextInt();
		int [] arr = new int[n];
		for (int i = 0; i < n; i++) {
			arr[i] = in.nextInt();
		}
		WritingCode x = new WritingCode(arr, new int [n][m+1][b+1], new boolean[n][m+1][b+1], b,mod);
		System.out.println(x.solve(0, m, 0) % mod);
	}

}


import java.util.*;
public class CdpD {
	public static void main(String args[]) {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		int m = sc.nextInt();
		int b = sc.nextInt();
		int mod = sc.nextInt();
		int[] arr = new int[n];
		for(int i=0; i<n; i++)
			arr[i] = sc.nextInt();
		int[][][] dp = new int[2][m+1][b+1];
		dp[0][0][0] = 1;
		for(int i=1; i<=n; i++) {
			int index = i&1;
			for(int j=0; j<=m; j++) {
				for(int k=0; k<=b; k++) {
					dp[index][j][k] = dp[index^1][j][k];
					if(j>0 && arr[i-1] <= k) {
						dp[index][j][k] = (dp[index][j][k]+dp[index][j-1][k-arr[i-1]]) % mod;
					}
				}
			}
		}
		int ans = 0;
		for(int k=0; k<=b; k++) {
			ans = (ans +dp[n&1][m][k]) % mod;
		}
		System.out.println(ans);
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	static int mod, a[];

	public static void main(String[] args) throws IOException {

		Scanner sc = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		int n = sc.nextInt(), m = sc.nextInt(), b = sc.nextInt();
		mod = sc.nextInt();
		a = new int[n];
		for(int i = 0; i < n; ++i)
			a[i] = sc.nextInt();

		int[][] lst, cur = new int[m+1][b+1];
		Arrays.fill(cur[0], 1);
		for(int pros = 0; pros < n; ++pros)
		{
			lst = cur;
			cur = new int[m+1][b+1];
			Arrays.fill(cur[0], 1);
			for(int lines = 1; lines <= m; ++lines)
				for(int bugs = 0; bugs <= b; ++bugs)
				{
					cur[lines][bugs] = lst[lines][bugs];
					if(bugs - a[pros] >= 0)
						cur[lines][bugs] = (cur[lines][bugs] + cur[lines-1][bugs-a[pros]])%mod;
				}

		}

		out.println(cur[m][b]);

		out.flush();
		out.close();
	}

	static class Scanner
	{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

		public String next() throws IOException
		{
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public int nextInt() throws IOException {return Integer.parseInt(next());}

		public long nextLong() throws IOException {return Long.parseLong(next());}

		public String nextLine() throws IOException {return br.readLine();}

		public double nextDouble() throws IOException
		{
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if(x.charAt(0) == '-')
			{
				neg = true;
				start++;
			}
			for(int i = start; i < x.length(); i++)
				if(x.charAt(i) == '.')
				{
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				}
				else
				{
					sb.append(x.charAt(i));
					if(dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg?-1:1);
		}

		public boolean ready() throws IOException {return br.ready();}

	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	static int mod, a[];
	static int[][][] memo;

	static int dp(int pros, int lines, int bugs)
	{
		if(bugs < 0)
			return 0;
		if(lines == -1)
			return 1;
		if(pros == -1)
			return 0;
		if(memo[pros][lines][bugs] != -1)
			return memo[pros][lines][bugs];

		return memo[pros][lines][bugs] = (dp(pros - 1, lines, bugs) + dp(pros, lines - 1, bugs - a[pros]))%mod;
	}

	public static void main(String[] args) throws IOException {

		Scanner sc = new Scanner(System.in);
		PrintWriter out = new PrintWriter(System.out);

		int n = sc.nextInt(), m = sc.nextInt(), b = sc.nextInt();
		mod = sc.nextInt();
		a = new int[n];
		for(int i = 0; i < n; ++i)
			a[i] = sc.nextInt();
		memo = new int[n][m][b + 1];
		for(int i = 0; i < n; ++i)
			for(int j = 0; j < m; ++j)
				Arrays.fill(memo[i][j], -1);

		out.println(dp(n - 1, m - 1, b)%mod);

		out.flush();
		out.close();
	}

	static class Scanner
	{
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

		public String next() throws IOException
		{
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public int nextInt() throws IOException {return Integer.parseInt(next());}

		public long nextLong() throws IOException {return Long.parseLong(next());}

		public String nextLine() throws IOException {return br.readLine();}

		public double nextDouble() throws IOException
		{
			String x = next();
			StringBuilder sb = new StringBuilder("0");
			double res = 0, f = 1;
			boolean dec = false, neg = false;
			int start = 0;
			if(x.charAt(0) == '-')
			{
				neg = true;
				start++;
			}
			for(int i = start; i < x.length(); i++)
				if(x.charAt(i) == '.')
				{
					res = Long.parseLong(sb.toString());
					sb = new StringBuilder("0");
					dec = true;
				}
				else
				{
					sb.append(x.charAt(i));
					if(dec)
						f *= 10;
				}
			res += Long.parseLong(sb.toString()) / f;
			return res * (neg?-1:1);
		}

		public boolean ready() throws IOException {return br.ready();}

	}
}


//package codeforces;

import java.util.Scanner;

/**
 * https://codeforces.com/problemset/problem/543/A
 */
public class WritingCode {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);

		int n = in.nextInt();
		int m = in.nextInt();
		int b = in.nextInt();
		int r = in.nextInt();

		int[] bugs = new int[n + 1];
		for (int i = 1; i <= n; i++) {
			bugs[i] = in.nextInt();
		}

		int[][] f = new int[m + 1][b + 1];
		int[][] g = new int[m + 1][b + 1];
		f[0][0] = 1;

		for (int i = 1; i <= n; i++) {
			for (int j = 0; j <= m; j++) {
				for (int k = 0; k <= b; k++) {
					g[j][k] = f[j][k];
					if (k >= bugs[i] && j >= 1) {
						g[j][k] += g[j - 1][k - bugs[i]];
					}
					g[j][k] %= r;
				}
			}
			f = g;
			g = new int[m + 1][b + 1];
		}

		int result = 0;
		for (int i = 0; i <= b; i++) {
			result += f[m][i];
			result %= r;
		}
		System.out.println(result);

		in.close();
	}
}


//package codeforces;

import java.util.Scanner;

/**
 * https://codeforces.com/problemset/problem/543/A
 */
public class WritingCode {

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);

		int n = in.nextInt();
		int m = in.nextInt();
		int b = in.nextInt();
		int r = in.nextInt();

		int[] bugs = new int[n + 1];
		for (int i = 1; i <= n; i++) {
			bugs[i] = in.nextInt();
		}

		int[][][] f = new int[n + 1][m + 1][b + 1];
		f[0][0][0] = 1;

		for (int i = 1; i <= n; i++) {
			for (int j = 0; j <= m; j++) {
				for (int k = 0; k <= b; k++) {
					f[i][j][k] = f[i - 1][j][k];
					if (k >= bugs[i] && j >= 1) {
						f[i][j][k] += f[i][j - 1][k - bugs[i]];
					}
					f[i][j][k] %= r;
				}
			}
		}

		int result = 0;
		for (int i = 0; i <= b; i++) {
			result += f[n][m][i];
			result %= r;
		}
		System.out.println(result);

		in.close();
	}
}


import java.io.*;
import java.util.*;

public class A {

    private static long modulo = 1000000007;

    private static void solve() {
        int n = in.nextInt();
        int m = in.nextInt();
        int b = in.nextInt();
        modulo = in.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = in.nextInt();
        }
        long[][] dp = new long[m + 1][b + 1];
        dp[0][0] = 1;
        for (int i = 0; i < n; i++) {
            for (int v = 0; v < m; v++) {
                for (int j = 0; j <= b; j++) {
                    if (j + a[i] <= b) {
                        dp[v + 1][j + a[i]] = (dp[v + 1][j + a[i]] + dp[v][j]) % modulo;
                    }
                }
            }
        }
        long result = 0;
        for (int j = 0; j <= b; j++) {
            result = (result + dp[m][j]) % modulo;
        }
        out.println(result);
    }

    private static long inverse(long a) {
        long result = 1;
        int n = (int) modulo - 2;
        while (n != 0) {
            if ((n & 1) == 1)
                result = (result * a) % modulo;
            a = (a * a) % modulo;
            n >>= 1;
        }
        return result;
    }

    private static long pow(long a, long n) {
        if (n == 0) return 1;
        if (n % 2 == 0) {
            long ans = pow(a, n / 2);
            return ans * ans;
        } else {
            return a * pow(a, n - 1);
        }
    }

    public static void main(String[] args) {
        solve();
        closeStreams();
    }

    private static void closeStreams() {
        in.close();
        out.close();
    }

    private static final FastScanner in = new FastScanner();
    private static final PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

    public static class FastScanner {

        private BufferedReader br;
        private StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        void close() {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}


import java.io.*;
import java.util.*;

public class A {

    private static long modulo = 1000000007;

    private static void solve() {
        int n = in.nextInt();
        int m = in.nextInt();
        int b = in.nextInt();
        modulo = in.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = in.nextInt();
        }
        int[][] dp = new int[m + 1][b + 1];
        dp[0][0] = 1;
        for (int i = 0; i < n; i++) {
            for (int v = 0; v < m; v++) {
                for (int j = 0; j <= b; j++) {
                    if (j + a[i] <= b) {
                        dp[v + 1][j + a[i]] += (dp[v + 1][j + a[i]] + dp[v][j + a[i]]) % modulo;
                    }
                }
            }
        }
        long result = 0;
        for (int j = 0; j <= b; j++) {
            result = (result + dp[m][j]) % modulo;
        }
        out.println(result);
    }

    private static long inverse(long a) {
        long result = 1;
        int n = (int) modulo - 2;
        while (n != 0) {
            if ((n & 1) == 1)
                result = (result * a) % modulo;
            a = (a * a) % modulo;
            n >>= 1;
        }
        return result;
    }

    private static long pow(long a, long n) {
        if (n == 0) return 1;
        if (n % 2 == 0) {
            long ans = pow(a, n / 2);
            return ans * ans;
        } else {
            return a * pow(a, n - 1);
        }
    }

    public static void main(String[] args) {
        solve();
        closeStreams();
    }

    private static void closeStreams() {
        in.close();
        out.close();
    }

    private static final FastScanner in = new FastScanner();
    private static final PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

    public static class FastScanner {

        private BufferedReader br;
        private StringTokenizer st;

        public FastScanner() {
            br = new BufferedReader(new InputStreamReader(System.in));
        }

        String next() {
            while (st == null || !st.hasMoreElements()) {
                try {
                    st = new StringTokenizer(br.readLine());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return st.nextToken();
        }

        int nextInt() {
            return Integer.parseInt(next());
        }

        long nextLong() {
            return Long.parseLong(next());
        }

        double nextDouble() {
            return Double.parseDouble(next());
        }

        String nextLine() {
            String str = "";
            try {
                str = br.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return str;
        }

        void close() {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}