#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define vi vector<int>
#define vll vector<ll>
const int maxn = 2e5 + 5;
const int mod = 1e9 + 7;
int a[maxn];
ll dp[maxn][17];
int states;
int main()
{
    ios::sync_with_stdio(false);
    string b; cin >> b;
    int n = b.size();
    int t; cin >> t;
    for (int i = 1 ; i <= n ; i++){
        if (isdigit(b[i - 1])) a[i] = b[i - 1] - '0';
        else a[i] = b[i - 1] - 'A' + 10;
    }
    for (int i = 0 ; i < n ; i++){
        for (int j = 1 ; j <= 16 ; j++){
            dp[i + 1][j] = (dp[i + 1][j] + dp[i][j] * j%mod)%mod;
            dp[i + 1][j + 1] = (dp[i + 1][j + 1] + dp[i][j] * (16 - j)%mod)%mod;
        }
        // 0
        dp[i + 1][0] = (dp[i + 1][0] + dp[i][0])%mod;
        dp[i + 1][1] = (dp[i + 1][1] + dp[i][0] * 15 % mod) % mod;
        for (int j = 0 ; j < a[i + 1] ; j++){
            int ns = states;
            // i = 0 , j = 0 只会发生在填第一位的时候，要特判
            if (i || j) ns |= (1 << j);
            dp[i + 1][__builtin_popcount(ns)] += 1;
        }

        states |= (1 << a[i + 1]);
    }
    cout << dp[n][t] + (t == __builtin_popcount(states)) << endl;
    return 0;
}

#include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<n;++i)
using namespace std;

template<typename T>
struct UnionFind {
	vector<int> d;
	//コンストラクタ
	UnionFind(int n = 0) : d(n, -1) {}
	//根の探索と張り替え
	int find(int x) {
		if (d[x] < 0) return x;
		//根のはりかえ
		return d[x] = find(d[x]);
	}
	//根の結合
	bool unite(int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) return false;
		//大きい方に小さい方をくっつける
		if (x < y) swap(x, y);
		//サイズの更新
		d[x] += d[y];
		//結合
		d[y] = x;
		return true;
	}
	//サイズの取得
	int size(int x) { return -d[find(x)]; }
	//同じ集合に属しているか
	bool same(int x, int y) { return (find(x) == find(y)); }
};

const int top = 100;
const int bottom = -100;

double dist(int x1, int x2, int y1, int y2)
{
    double dx = (double) x1-x2;
    double dy = (double) y1-y2;
    return dx*dx+dy*dy;
}

int main()
{
    int n; cin >> n;
    vector<int> x(n);
    vector<int> y(n);
    rep(i,n) cin >> x[i] >> y[i];

    double up = 200, low = 0;

    rep(bi,80)
    {
        double mid = (up+low)/2;
        UnionFind<int> uf(n+2);
        //壁同士の判定
        if(top-mid < bottom + mid) uf.unite(n,n+1);
        //上下の壁との判定
        rep(i,n)
        {
            if(y[i] + mid > top - mid) uf.unite(i,n);
            if(y[i] - mid < bottom + mid) uf.unite(i,n+1);
        }
        //釘同士の判定
        rep(i,n)rep(j,n)
        {
            if(i > j) continue;
            if(dist(x[i],x[j],y[i],y[j]) < 4*mid*mid) uf.unite(i,j);         
        }
        if(uf.same(n,n+1)) up = mid;
        else low = mid;
    }
    cout << setprecision(7) <<endl;
    cout << low << endl;
}