#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<pii> vii;
typedef vector<pll> vll;
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define ff first
#define ss second
#define mp make_pair

int n, kand = 1;
string A, B;
mt19937 rng;
vl dp, nast;
vi pierw, odw, aktyw, nxt;
int iter = 0;

bool cmp(int a, int b){
    return a > b;
}

ll mulmod(ll a, ll b, ll mod){
    a %= mod; b %= mod;
    return (a * b) % mod;
}

ll powmod(ll a, ll b, ll mod){
    ll r = 1;
    while(b){
        if(b & 1) r = mulmod(r, a, mod);
        a = mulmod(a, a, mod);
        b >>= 1;
    }
    return r;
}

ll ext(ll a, ll b, ll& x, ll& y){
    if(b == 0){
        x = 1; y = 0;
        return a;
    }
    ll x1, y1, g = ext(b, a % b, x1, y1);
    x = y1; y = x1 - (a / b) * y1;
    return g;
}

ll inv(ll a, ll b){
    ll x, y; ext(a, b, x, y);
    x %= b; if(x < 0) x += b;
    return x;
}

ll rhopom(ll x, ll m, ll c){
    return (mulmod(x, x, m) + c) % m;
}

bool czy_pierwsza(int x){
    if(x < 2) return false;
    for(int p : {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37}){
        if(x % p == 0) return x == p;
    }

    int d = x - 1, s = 0;
    while(!(d & 1)){
        d >>= 1; s++;
    }
    for(int a : {2, 7, 61}){
        if(a % x == 0) continue;
        ll z = powmod(a, d, x);
        if(z == 1 || z == x - 1) continue;
        bool czy = true;
        for(int b = 1; b < s; b++){
            z = mulmod(z, z, x);
            if(z == x - 1){
                czy = false; break;
            }
        }
        if(czy) return false;
    }
    return true;
}

ll pollardRho(int m){
    if(m % 2 == 0) return 2;
    if(m % 3 == 0) return 3;
    for(;;){
        ll c = (ll)(rng() % (m - 1)) + 1;
        ll x = (ll)(rng() % (m - 2)) + 2;
        ll y = x, d = 1;
        for(int it = 0; d == 1 && it < 100000; it++){
            x = rhopom(x, m, c);
            y = rhopom(rhopom(y, m, c), m, c);
            d = __gcd(abs(x - y), ll(m));
        }
        if(d > 1 && d < m) return d;
    }
}

void faktoryzuj(int x, vi& f){
    if(x == 1) return;
    for(int p : pierw){
        if(p * p > x) break;
        while(x % p == 0){
            f.pb(p); x /= p;
        }
        if(x == 1) return;
    }
    if(x == 1) return;
    if(czy_pierwsza(x)){
        f.pb(x); return;
    }
    ll d = pollardRho(x);
    faktoryzuj(d, f);
    faktoryzuj(x / d, f);
}

void dzielniki(int x, vi& dziel){
    vi f;
    faktoryzuj(x, f);
    sort(all(f));
    dziel.clear(); dziel.pb(1);
    int m = f.size();
    for(int i = 0; i < m; i++){
        int j = i;
        while(j < m && f[i] == f[j]) j++;
        int last = dziel.size(), akt = 1;
        for(int w = i; w < j; w++){
            akt *= f[i];
            for(int k = 0; k < last; k++){
                dziel.pb(akt * dziel[k]);
            }
        }
        i = j - 1;
    }
}

struct info{
    string s;
    int mn, mx;
    vi poza;
    int pocz, dl, suf;
    ll W, M;
    bool czy;
};

int skrajne(string& a, int b){
    int val = 0;
    for(char c : a){
        int x = b;
        if(c != '?') x = int(c - '0');
        val *= 10; val += x;
    }
    return val;
}

int ile_zap(string& a){
    int x = 0;
    for(char c : a) if(c == '?') x++;
    return x;
}

bool czy_pasuje(string& a, int d){
    if(d <= 0) return false;
    for(int i = n - 1; i >= 0; i--){
        int r = d % 10; d /= 10;
        if(a[i] != '?' && int(a[i] - '0') != r) return false;
    }
    return d == 0;
}

info prep(string& a){
    int mn = skrajne(a, 0), mx = skrajne(a, 9);
    vii przedzialy;
    for(int i = 0; i < n; i++){
        if(a[i] != '?') continue;
        int j = i;
        while(j < n && a[j] == '?') j++;
        przedzialy.pb(mp(i, j - i));
        i = j;
    }

    int pocz = -1, dl = 0;
    for(pii& kand : przedzialy){
        if(kand.ss > dl){
            pocz = kand.ff; dl = kand.ss;
        }
    }
    vi pos;
    ll M = 1, W = 1;
    int suf = n - (pocz + dl);
    if(dl){
        for(int i = 0; i < pocz; i++) if(a[i] == '?') pos.pb(i);
        for(int i = pocz + dl; i < n; i++) if(a[i] == '?') pos.pb(i);
        for(int i = 0; i < suf; i++) W *= 10;
        for(int i = 0; i < dl; i++) M *= 10;
    }
    return {a, mn, mx, pos, pocz, dl, suf, W, M, 1 - przedzialy.empty()};
}

bool tozsame(){
    for(int i = 0; i < n; i++)
        if(A[i] != '?' && B[i] != '?' && A[i] != B[i])
            return false;
    return true;
}

int wsp_max(){
    int val = 0;
    for(int i = 0; i < n; i++){
        char pom;
        int x;
        if(A[i] != '?') pom = A[i];
        else pom = B[i];
        if(pom == '?') x = 9;
        else x = int(pom - '0');
        val *= 10; val += x;
    }
    return val;
}

void prep_pierwsze(){
    const int N = 1000;
    vi f(N + 1, 0);
    for(int i = 2; i <= N; i++){
        if(!f[i]){
            for(int j = i * i; j <= N; j += i) f[j] = 1;
        }
    }
    for(int i = 2; i <= N; i++) if(!f[i]) pierw.pb(i);
}

bool spr_row_diof(ll a, ll b, ll d, ll lim){
    ll g = __gcd(b, d);
    if(a % g != 0) return false;

    ll nd = d / g;

    if(nd < lim) return true;
    if(nd == lim) return a > 0;

    ll pom = (nd - (a / g) % nd) % nd;
    ll z = mulmod(pom, inv((b / g) % nd, nd), nd);

    return z < lim && (a > 0 || z > 0);
}

bool czy_dziala_d_pom(string& s, int pos, info& a, int d){
    if(pos == a.poza.size()){
        ll x = 0;
        for(char c : s){
            x *= 10;
            x += c - '0';
        }
        return spr_row_diof(x, a.W, d, a.M);
    }

    int i = a.poza[pos];

    for(int z = 0; z <= 9; z++){
        s[i] = char('0' + z);

        if(czy_dziala_d_pom(s, pos + 1, a, d)){
            s[i] = '?';
            return true;
        }
    }

    s[i] = '?';
    return false;
}

bool czy_dziala_d(int d, info& a){
    int l = max(1, (a.mn + d - 1) / d);
    int r = a.mx / d;

    if(r - l <= 20000){
        for(int i = l; i <= r; i++){
            if(czy_pasuje(a.s, d * i))
                return true;
        }
        return false;
    }

    string t = a.s;
    for(int i = a.pocz; i < a.pocz + a.dl; i++) t[i] = '0';

    return czy_dziala_d_pom(t, 0, a, d);
}

void solver1_pom(string& s, info& b, int pos, ll val, vl& p10, vl& mxs, unordered_map<int, bool>& pam){

    if(val * p10[n - pos] + mxs[pos] <= kand) return;

    if(pos == n){
        int x = val;

        if(x == 0) return;

        vi dziel;
        dzielniki(x, dziel);
        sort(all(dziel), cmp);

        for(int d : dziel){
            if(d <= kand) break;
            auto it = pam.find(d);
            bool ok;
            if(it != pam.end()) ok = it->ss;
            else ok = pam[d] = czy_dziala_d(d, b);

            if(ok){
                kand = d;
                break;
            }
        }
        return;
    }

    if(s[pos] != '?'){
        solver1_pom(s, b, pos + 1, val * 10 + s[pos] - '0', p10, mxs, pam);
        return;
    }

    for(int z = 9; z >= 0; z--){
        ll nv = val * 10 + z;
        if(nv * p10[n - pos - 1] + mxs[pos + 1] <= kand) break;
        solver1_pom(s, b, pos + 1, nv, p10, mxs, pam);
    }
}

void solver1(string& s, info& b){
    unordered_map<int, bool> pam;

    vl p10(n + 1, 1), mxs(n + 1, 0);

    for(int i = 1; i <= n; i++) p10[i] = p10[i - 1] * 10;
    for(int i = n - 1; i >= 0; i--){
        int x = int(s[i] - '0');
        if(s[i] == '?') x = 9;
        mxs[i] = x * p10[n - i - 1] + mxs[i + 1];
    }

    solver1_pom(s, b, 0, 0, p10, mxs, pam);
}

int solver2_pom(int p, int q, info& a, info& b){
    ll lim = min(a.mx / p, b.mx / q);
    ll dol = max(1LL, max(1ll * (a.mn + p - 1) / p, 1ll * (b.mn + q - 1) / q));

    if(lim <= kand || dol > lim) return 0;

    int roz = p * q;
    if(dp.size() < roz){
        dp.resize(roz);
        nast.resize(roz);
        odw.resize(roz, 0);
    }
    aktyw.clear();
    nxt.clear();

    aktyw.pb(0);
    dp[0] = 0;

    ll pot = 1;

    for(int i = n - 1; i >= 0; i--){
        nxt.clear();

        if(iter == INT_MAX){
            fill(all(odw), 0);
            iter = 0;
        }
        iter++;

        for(int j : aktyw){
            int ca = j / q, cb = j % q;
            ll val = dp[j];

            if(val > lim) continue;

            ll first = val;
            if(first < dol) first += (dol - first + pot - 1) / pot * pot;
            if(first > lim) continue;

            ll last = val + (lim - val) / pot * pot;
            if(last <= kand) continue;

            for(int z = 0; z <= 9; z++){
                int x = p * z + ca, y = q * z + cb, da = x % 10, db = y % 10;

                if(a.s[i] != '?' && a.s[i] - '0' != da) continue;
                if(b.s[i] != '?' && b.s[i] - '0' != db) continue;

                int na = x / 10, nb = y / 10, l = na * q + nb;
                ll nv = val + z * pot;
                if(odw[l] != iter){
                    odw[l] = iter;
                    nast[l] = nv;
                    nxt.pb(l);
                }else nast[l] = max(nast[l], nv);
            }
        }

        dp.swap(nast);
        aktyw.swap(nxt);

        if(aktyw.empty()) return 0;

        pot *= 10;
    }

    if(odw[0] != iter) return 0;
    return dp[0];
}


void solver2(bool& czy, info& a, info& b){
    const int K = 1200;
    int t = max(a.mx, b.mx);
    czy = false;

    aktyw.reserve(2 * K + 5);
    nxt.reserve(2 * K + 5);

    for(int k = 1; k <= K; k++){
        if(t / k <= kand){
            czy = true;
            return;
        }

        for(int p = 1; p <= k; p++){
            int q = k;
            if(min(a.mx / p, b.mx / q) <= kand) break;
            if(__gcd(p, q) != 1) continue;
            kand = max(kand, solver2_pom(p, q, a, b));
            if(t / k <= kand){
                czy = true;
                return;
            }
        }

        for(int q = 1; q < k; q++){
            int p = k;
            if(min(a.mx / p, b.mx / q) <= kand) break;
            if(__gcd(p, q) != 1) continue;
            kand = max(kand, solver2_pom(p, q, a, b));
            if(t / k <= kand){
                czy = true;
                return;
            }
        }

        if(t / (k + 1) <= kand){
            czy = true;
            return;
        }
    }
}

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

    rng.seed(67);
    cin >> n >> A >> B;

    info ia = prep(A), ib = prep(B);

    if(tozsame()){
        kand = wsp_max();
        if(kand == min(ia.mx, ib.mx) || 2 * kand >= max(ia.mx, ib.mx)){
            cout << kand << "\n";
            return 0;
        }
    }

    int qa = ile_zap(A), qb = ile_zap(B);

    if(min(qa, qb) <= 5){
        prep_pierwsze();
        if(qa <= qb) solver1(A, ib);
        else solver1(B, ia);

        cout << kand << "\n";
        return 0;
    }

    bool czy;
    solver2(czy, ia, ib);

    if(!czy){
        prep_pierwsze();
        if(qa <= qb) solver1(A, ib);
        else solver1(B, ia);
    }

    cout << kand << "\n";
    return 0;
}
