#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll N=1e3+5;
string s;          // 存储每个节点的二进制位(0/1)
vector<vector<ll>>adj(N);  // 树的双向邻接表
ll n,l,r;          // n:节点数;l/r:二进制值的范围上下限
ll cnt=0;          // 统计符合条件的路径数量
unordered_map<ll,bool>m;   // 标记节点是否已访问(防DFS回退、走重复节点)

// DFS核心函数:遍历以x为当前节点的路径,sum为当前路径的二进制值
// 算法步骤:1.遍历当前节点的所有邻接节点 2.防回退 3.计算新路径的二进制值 4.判断是否在范围 5.剪枝 6.递归遍历下一个节点 7.回溯恢复标记
void dfs(ll x,ll sum){
    // 步骤1:遍历当前节点x的所有邻接节点t
    for(auto t:adj[x]){
        // 步骤2:防回退(跳过已访问的节点,避免走回头路形成环)
        if(m[t]!=false)continue;
        
        // 步骤3:计算新增节点t后的路径二进制值(左移1位 += 当前节点t的二进制值)
        ll n_sum=sum<<1;  // 二进制左移1位 = 数值×2
        if(s[t-1]-'0'==1){  // 节点t的二进制位是1,加到新值中
            n_sum+=1;
        }
        
        // 步骤4:判断新路径值是否在[l,r]范围内,符合则计数+1
        if(n_sum>=l&&n_sum<=r){
            cnt++;
        }
        // 步骤5:剪枝优化:若新值已超过r,后续路径只会更大,直接跳过该分支
        else if(n_sum>r){
            continue;
        }
        
        // 步骤6:标记节点t为已访问,递归遍历以t为当前节点的后续路径
        m[t]=true;
        dfs(t,n_sum);
        // 步骤7:回溯:恢复节点t的未访问状态,供其他分支遍历
        m[t]=false;
    }
}

int main(){
    ios::sync_with_stdio(0),cin.tie(0);  // 加速cin/cout输入输出
    cin>>n>>l>>r;  // 输入节点数、范围上下限
    cin>>s;        // 输入每个节点的二进制位(s[0]对应节点1,s[1]对应节点2...)
    
    // 步骤1:构建树的双向邻接表(树是无向图,需双向存储边)
    for(ll i=1;i<=n-1;i++){
        ll u,v;
        cin>>u>>v;
        adj[u].emplace_back(v);
        adj[v].emplace_back(u);
        m[u]=false;  // 初始化节点访问标记为未访问
        m[v]=false;
    }
    
    // 边界处理:只有1个节点时无路径,直接输出0
    if(n==1){
        cout<<0;
        return 0;
    }
    
    // 步骤2:枚举每个节点作为路径的起点
    for(ll i=1;i<=n;i++){
        m[i]=true;  // 标记起点为已访问(避免路径包含自身)
        // 调用DFS:起点为i,初始路径值为节点i的二进制位
        dfs(i,s[i-1]-'0');
        m[i]=false; // 回溯:恢复起点的未访问状态
    }
    
    // 步骤3:输出符合条件的路径总数
    cout<<cnt;
    return 0;
}