#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;
}
I2luY2x1ZGU8Yml0cy9zdGRjKysuaD4KdXNpbmcgbmFtZXNwYWNlIHN0ZDsKdHlwZWRlZiBsb25nIGxvbmcgbGw7CnR5cGVkZWYgbG9uZyBkb3VibGUgbGQ7CnR5cGVkZWYgcGFpcjxpbnQsIGludD4gcGlpOwp0eXBlZGVmIHBhaXI8bGwsIGxsPiBwbGw7CnR5cGVkZWYgdmVjdG9yPGludD4gdmk7CnR5cGVkZWYgdmVjdG9yPGxsPiB2bDsKdHlwZWRlZiB2ZWN0b3I8cGlpPiB2aWk7CnR5cGVkZWYgdmVjdG9yPHBsbD4gdmxsOwojZGVmaW5lIGFsbCh4KSAoeCkuYmVnaW4oKSwoeCkuZW5kKCkKI2RlZmluZSBwYiBwdXNoX2JhY2sKI2RlZmluZSBmZiBmaXJzdAojZGVmaW5lIHNzIHNlY29uZAojZGVmaW5lIG1wIG1ha2VfcGFpcgoKaW50IG4sIGthbmQgPSAxOwpzdHJpbmcgQSwgQjsKbXQxOTkzNyBybmc7CnZsIGRwLCBuYXN0Owp2aSBwaWVydywgb2R3LCBha3R5dywgbnh0OwppbnQgaXRlciA9IDA7Cgpib29sIGNtcChpbnQgYSwgaW50IGIpewogICAgcmV0dXJuIGEgPiBiOwp9CgpsbCBtdWxtb2QobGwgYSwgbGwgYiwgbGwgbW9kKXsKICAgIGEgJT0gbW9kOyBiICU9IG1vZDsKICAgIHJldHVybiAoYSAqIGIpICUgbW9kOwp9CgpsbCBwb3dtb2QobGwgYSwgbGwgYiwgbGwgbW9kKXsKICAgIGxsIHIgPSAxOwogICAgd2hpbGUoYil7CiAgICAgICAgaWYoYiAmIDEpIHIgPSBtdWxtb2QociwgYSwgbW9kKTsKICAgICAgICBhID0gbXVsbW9kKGEsIGEsIG1vZCk7CiAgICAgICAgYiA+Pj0gMTsKICAgIH0KICAgIHJldHVybiByOwp9CgpsbCBleHQobGwgYSwgbGwgYiwgbGwmIHgsIGxsJiB5KXsKICAgIGlmKGIgPT0gMCl7CiAgICAgICAgeCA9IDE7IHkgPSAwOwogICAgICAgIHJldHVybiBhOwogICAgfQogICAgbGwgeDEsIHkxLCBnID0gZXh0KGIsIGEgJSBiLCB4MSwgeTEpOwogICAgeCA9IHkxOyB5ID0geDEgLSAoYSAvIGIpICogeTE7CiAgICByZXR1cm4gZzsKfQoKbGwgaW52KGxsIGEsIGxsIGIpewogICAgbGwgeCwgeTsgZXh0KGEsIGIsIHgsIHkpOwogICAgeCAlPSBiOyBpZih4IDwgMCkgeCArPSBiOwogICAgcmV0dXJuIHg7Cn0KCmxsIHJob3BvbShsbCB4LCBsbCBtLCBsbCBjKXsKICAgIHJldHVybiAobXVsbW9kKHgsIHgsIG0pICsgYykgJSBtOwp9Cgpib29sIGN6eV9waWVyd3N6YShpbnQgeCl7CiAgICBpZih4IDwgMikgcmV0dXJuIGZhbHNlOwogICAgZm9yKGludCBwIDogezIsIDMsIDUsIDcsIDExLCAxMywgMTcsIDE5LCAyMywgMjksIDMxLCAzN30pewogICAgICAgIGlmKHggJSBwID09IDApIHJldHVybiB4ID09IHA7CiAgICB9CgogICAgaW50IGQgPSB4IC0gMSwgcyA9IDA7CiAgICB3aGlsZSghKGQgJiAxKSl7CiAgICAgICAgZCA+Pj0gMTsgcysrOwogICAgfQogICAgZm9yKGludCBhIDogezIsIDcsIDYxfSl7CiAgICAgICAgaWYoYSAlIHggPT0gMCkgY29udGludWU7CiAgICAgICAgbGwgeiA9IHBvd21vZChhLCBkLCB4KTsKICAgICAgICBpZih6ID09IDEgfHwgeiA9PSB4IC0gMSkgY29udGludWU7CiAgICAgICAgYm9vbCBjenkgPSB0cnVlOwogICAgICAgIGZvcihpbnQgYiA9IDE7IGIgPCBzOyBiKyspewogICAgICAgICAgICB6ID0gbXVsbW9kKHosIHosIHgpOwogICAgICAgICAgICBpZih6ID09IHggLSAxKXsKICAgICAgICAgICAgICAgIGN6eSA9IGZhbHNlOyBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZihjenkpIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHJldHVybiB0cnVlOwp9CgpsbCBwb2xsYXJkUmhvKGludCBtKXsKICAgIGlmKG0gJSAyID09IDApIHJldHVybiAyOwogICAgaWYobSAlIDMgPT0gMCkgcmV0dXJuIDM7CiAgICBmb3IoOzspewogICAgICAgIGxsIGMgPSAobGwpKHJuZygpICUgKG0gLSAxKSkgKyAxOwogICAgICAgIGxsIHggPSAobGwpKHJuZygpICUgKG0gLSAyKSkgKyAyOwogICAgICAgIGxsIHkgPSB4LCBkID0gMTsKICAgICAgICBmb3IoaW50IGl0ID0gMDsgZCA9PSAxICYmIGl0IDwgMTAwMDAwOyBpdCsrKXsKICAgICAgICAgICAgeCA9IHJob3BvbSh4LCBtLCBjKTsKICAgICAgICAgICAgeSA9IHJob3BvbShyaG9wb20oeSwgbSwgYyksIG0sIGMpOwogICAgICAgICAgICBkID0gX19nY2QoYWJzKHggLSB5KSwgbGwobSkpOwogICAgICAgIH0KICAgICAgICBpZihkID4gMSAmJiBkIDwgbSkgcmV0dXJuIGQ7CiAgICB9Cn0KCnZvaWQgZmFrdG9yeXp1aihpbnQgeCwgdmkmIGYpewogICAgaWYoeCA9PSAxKSByZXR1cm47CiAgICBmb3IoaW50IHAgOiBwaWVydyl7CiAgICAgICAgaWYocCAqIHAgPiB4KSBicmVhazsKICAgICAgICB3aGlsZSh4ICUgcCA9PSAwKXsKICAgICAgICAgICAgZi5wYihwKTsgeCAvPSBwOwogICAgICAgIH0KICAgICAgICBpZih4ID09IDEpIHJldHVybjsKICAgIH0KICAgIGlmKHggPT0gMSkgcmV0dXJuOwogICAgaWYoY3p5X3BpZXJ3c3phKHgpKXsKICAgICAgICBmLnBiKHgpOyByZXR1cm47CiAgICB9CiAgICBsbCBkID0gcG9sbGFyZFJobyh4KTsKICAgIGZha3Rvcnl6dWooZCwgZik7CiAgICBmYWt0b3J5enVqKHggLyBkLCBmKTsKfQoKdm9pZCBkemllbG5pa2koaW50IHgsIHZpJiBkemllbCl7CiAgICB2aSBmOwogICAgZmFrdG9yeXp1aih4LCBmKTsKICAgIHNvcnQoYWxsKGYpKTsKICAgIGR6aWVsLmNsZWFyKCk7IGR6aWVsLnBiKDEpOwogICAgaW50IG0gPSBmLnNpemUoKTsKICAgIGZvcihpbnQgaSA9IDA7IGkgPCBtOyBpKyspewogICAgICAgIGludCBqID0gaTsKICAgICAgICB3aGlsZShqIDwgbSAmJiBmW2ldID09IGZbal0pIGorKzsKICAgICAgICBpbnQgbGFzdCA9IGR6aWVsLnNpemUoKSwgYWt0ID0gMTsKICAgICAgICBmb3IoaW50IHcgPSBpOyB3IDwgajsgdysrKXsKICAgICAgICAgICAgYWt0ICo9IGZbaV07CiAgICAgICAgICAgIGZvcihpbnQgayA9IDA7IGsgPCBsYXN0OyBrKyspewogICAgICAgICAgICAgICAgZHppZWwucGIoYWt0ICogZHppZWxba10pOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGkgPSBqIC0gMTsKICAgIH0KfQoKc3RydWN0IGluZm97CiAgICBzdHJpbmcgczsKICAgIGludCBtbiwgbXg7CiAgICB2aSBwb3phOwogICAgaW50IHBvY3osIGRsLCBzdWY7CiAgICBsbCBXLCBNOwogICAgYm9vbCBjenk7Cn07CgppbnQgc2tyYWpuZShzdHJpbmcmIGEsIGludCBiKXsKICAgIGludCB2YWwgPSAwOwogICAgZm9yKGNoYXIgYyA6IGEpewogICAgICAgIGludCB4ID0gYjsKICAgICAgICBpZihjICE9ICc/JykgeCA9IGludChjIC0gJzAnKTsKICAgICAgICB2YWwgKj0gMTA7IHZhbCArPSB4OwogICAgfQogICAgcmV0dXJuIHZhbDsKfQoKaW50IGlsZV96YXAoc3RyaW5nJiBhKXsKICAgIGludCB4ID0gMDsKICAgIGZvcihjaGFyIGMgOiBhKSBpZihjID09ICc/JykgeCsrOwogICAgcmV0dXJuIHg7Cn0KCmJvb2wgY3p5X3Bhc3VqZShzdHJpbmcmIGEsIGludCBkKXsKICAgIGlmKGQgPD0gMCkgcmV0dXJuIGZhbHNlOwogICAgZm9yKGludCBpID0gbiAtIDE7IGkgPj0gMDsgaS0tKXsKICAgICAgICBpbnQgciA9IGQgJSAxMDsgZCAvPSAxMDsKICAgICAgICBpZihhW2ldICE9ICc/JyAmJiBpbnQoYVtpXSAtICcwJykgIT0gcikgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIGQgPT0gMDsKfQoKaW5mbyBwcmVwKHN0cmluZyYgYSl7CiAgICBpbnQgbW4gPSBza3Jham5lKGEsIDApLCBteCA9IHNrcmFqbmUoYSwgOSk7CiAgICB2aWkgcHJ6ZWR6aWFseTsKICAgIGZvcihpbnQgaSA9IDA7IGkgPCBuOyBpKyspewogICAgICAgIGlmKGFbaV0gIT0gJz8nKSBjb250aW51ZTsKICAgICAgICBpbnQgaiA9IGk7CiAgICAgICAgd2hpbGUoaiA8IG4gJiYgYVtqXSA9PSAnPycpIGorKzsKICAgICAgICBwcnplZHppYWx5LnBiKG1wKGksIGogLSBpKSk7CiAgICAgICAgaSA9IGo7CiAgICB9CgogICAgaW50IHBvY3ogPSAtMSwgZGwgPSAwOwogICAgZm9yKHBpaSYga2FuZCA6IHByemVkemlhbHkpewogICAgICAgIGlmKGthbmQuc3MgPiBkbCl7CiAgICAgICAgICAgIHBvY3ogPSBrYW5kLmZmOyBkbCA9IGthbmQuc3M7CiAgICAgICAgfQogICAgfQogICAgdmkgcG9zOwogICAgbGwgTSA9IDEsIFcgPSAxOwogICAgaW50IHN1ZiA9IG4gLSAocG9jeiArIGRsKTsKICAgIGlmKGRsKXsKICAgICAgICBmb3IoaW50IGkgPSAwOyBpIDwgcG9jejsgaSsrKSBpZihhW2ldID09ICc/JykgcG9zLnBiKGkpOwogICAgICAgIGZvcihpbnQgaSA9IHBvY3ogKyBkbDsgaSA8IG47IGkrKykgaWYoYVtpXSA9PSAnPycpIHBvcy5wYihpKTsKICAgICAgICBmb3IoaW50IGkgPSAwOyBpIDwgc3VmOyBpKyspIFcgKj0gMTA7CiAgICAgICAgZm9yKGludCBpID0gMDsgaSA8IGRsOyBpKyspIE0gKj0gMTA7CiAgICB9CiAgICByZXR1cm4ge2EsIG1uLCBteCwgcG9zLCBwb2N6LCBkbCwgc3VmLCBXLCBNLCAxIC0gcHJ6ZWR6aWFseS5lbXB0eSgpfTsKfQoKYm9vbCB0b3pzYW1lKCl7CiAgICBmb3IoaW50IGkgPSAwOyBpIDwgbjsgaSsrKQogICAgICAgIGlmKEFbaV0gIT0gJz8nICYmIEJbaV0gIT0gJz8nICYmIEFbaV0gIT0gQltpXSkKICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgcmV0dXJuIHRydWU7Cn0KCmludCB3c3BfbWF4KCl7CiAgICBpbnQgdmFsID0gMDsKICAgIGZvcihpbnQgaSA9IDA7IGkgPCBuOyBpKyspewogICAgICAgIGNoYXIgcG9tOwogICAgICAgIGludCB4OwogICAgICAgIGlmKEFbaV0gIT0gJz8nKSBwb20gPSBBW2ldOwogICAgICAgIGVsc2UgcG9tID0gQltpXTsKICAgICAgICBpZihwb20gPT0gJz8nKSB4ID0gOTsKICAgICAgICBlbHNlIHggPSBpbnQocG9tIC0gJzAnKTsKICAgICAgICB2YWwgKj0gMTA7IHZhbCArPSB4OwogICAgfQogICAgcmV0dXJuIHZhbDsKfQoKdm9pZCBwcmVwX3BpZXJ3c3plKCl7CiAgICBjb25zdCBpbnQgTiA9IDEwMDA7CiAgICB2aSBmKE4gKyAxLCAwKTsKICAgIGZvcihpbnQgaSA9IDI7IGkgPD0gTjsgaSsrKXsKICAgICAgICBpZighZltpXSl7CiAgICAgICAgICAgIGZvcihpbnQgaiA9IGkgKiBpOyBqIDw9IE47IGogKz0gaSkgZltqXSA9IDE7CiAgICAgICAgfQogICAgfQogICAgZm9yKGludCBpID0gMjsgaSA8PSBOOyBpKyspIGlmKCFmW2ldKSBwaWVydy5wYihpKTsKfQoKYm9vbCBzcHJfcm93X2Rpb2YobGwgYSwgbGwgYiwgbGwgZCwgbGwgbGltKXsKICAgIGxsIGcgPSBfX2djZChiLCBkKTsKICAgIGlmKGEgJSBnICE9IDApIHJldHVybiBmYWxzZTsKCiAgICBsbCBuZCA9IGQgLyBnOwoKICAgIGlmKG5kIDwgbGltKSByZXR1cm4gdHJ1ZTsKICAgIGlmKG5kID09IGxpbSkgcmV0dXJuIGEgPiAwOwoKICAgIGxsIHBvbSA9IChuZCAtIChhIC8gZykgJSBuZCkgJSBuZDsKICAgIGxsIHogPSBtdWxtb2QocG9tLCBpbnYoKGIgLyBnKSAlIG5kLCBuZCksIG5kKTsKCiAgICByZXR1cm4geiA8IGxpbSAmJiAoYSA+IDAgfHwgeiA+IDApOwp9Cgpib29sIGN6eV9kemlhbGFfZF9wb20oc3RyaW5nJiBzLCBpbnQgcG9zLCBpbmZvJiBhLCBpbnQgZCl7CiAgICBpZihwb3MgPT0gYS5wb3phLnNpemUoKSl7CiAgICAgICAgbGwgeCA9IDA7CiAgICAgICAgZm9yKGNoYXIgYyA6IHMpewogICAgICAgICAgICB4ICo9IDEwOwogICAgICAgICAgICB4ICs9IGMgLSAnMCc7CiAgICAgICAgfQogICAgICAgIHJldHVybiBzcHJfcm93X2Rpb2YoeCwgYS5XLCBkLCBhLk0pOwogICAgfQoKICAgIGludCBpID0gYS5wb3phW3Bvc107CgogICAgZm9yKGludCB6ID0gMDsgeiA8PSA5OyB6KyspewogICAgICAgIHNbaV0gPSBjaGFyKCcwJyArIHopOwoKICAgICAgICBpZihjenlfZHppYWxhX2RfcG9tKHMsIHBvcyArIDEsIGEsIGQpKXsKICAgICAgICAgICAgc1tpXSA9ICc/JzsKICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgfQogICAgfQoKICAgIHNbaV0gPSAnPyc7CiAgICByZXR1cm4gZmFsc2U7Cn0KCmJvb2wgY3p5X2R6aWFsYV9kKGludCBkLCBpbmZvJiBhKXsKICAgIGludCBsID0gbWF4KDEsIChhLm1uICsgZCAtIDEpIC8gZCk7CiAgICBpbnQgciA9IGEubXggLyBkOwoKICAgIGlmKHIgLSBsIDw9IDIwMDAwKXsKICAgICAgICBmb3IoaW50IGkgPSBsOyBpIDw9IHI7IGkrKyl7CiAgICAgICAgICAgIGlmKGN6eV9wYXN1amUoYS5zLCBkICogaSkpCiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQoKICAgIHN0cmluZyB0ID0gYS5zOwogICAgZm9yKGludCBpID0gYS5wb2N6OyBpIDwgYS5wb2N6ICsgYS5kbDsgaSsrKSB0W2ldID0gJzAnOwoKICAgIHJldHVybiBjenlfZHppYWxhX2RfcG9tKHQsIDAsIGEsIGQpOwp9Cgp2b2lkIHNvbHZlcjFfcG9tKHN0cmluZyYgcywgaW5mbyYgYiwgaW50IHBvcywgbGwgdmFsLCB2bCYgcDEwLCB2bCYgbXhzLCB1bm9yZGVyZWRfbWFwPGludCwgYm9vbD4mIHBhbSl7CgogICAgaWYodmFsICogcDEwW24gLSBwb3NdICsgbXhzW3Bvc10gPD0ga2FuZCkgcmV0dXJuOwoKICAgIGlmKHBvcyA9PSBuKXsKICAgICAgICBpbnQgeCA9IHZhbDsKCiAgICAgICAgaWYoeCA9PSAwKSByZXR1cm47CgogICAgICAgIHZpIGR6aWVsOwogICAgICAgIGR6aWVsbmlraSh4LCBkemllbCk7CiAgICAgICAgc29ydChhbGwoZHppZWwpLCBjbXApOwoKICAgICAgICBmb3IoaW50IGQgOiBkemllbCl7CiAgICAgICAgICAgIGlmKGQgPD0ga2FuZCkgYnJlYWs7CiAgICAgICAgICAgIGF1dG8gaXQgPSBwYW0uZmluZChkKTsKICAgICAgICAgICAgYm9vbCBvazsKICAgICAgICAgICAgaWYoaXQgIT0gcGFtLmVuZCgpKSBvayA9IGl0LT5zczsKICAgICAgICAgICAgZWxzZSBvayA9IHBhbVtkXSA9IGN6eV9kemlhbGFfZChkLCBiKTsKCiAgICAgICAgICAgIGlmKG9rKXsKICAgICAgICAgICAgICAgIGthbmQgPSBkOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuOwogICAgfQoKICAgIGlmKHNbcG9zXSAhPSAnPycpewogICAgICAgIHNvbHZlcjFfcG9tKHMsIGIsIHBvcyArIDEsIHZhbCAqIDEwICsgc1twb3NdIC0gJzAnLCBwMTAsIG14cywgcGFtKTsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgZm9yKGludCB6ID0gOTsgeiA+PSAwOyB6LS0pewogICAgICAgIGxsIG52ID0gdmFsICogMTAgKyB6OwogICAgICAgIGlmKG52ICogcDEwW24gLSBwb3MgLSAxXSArIG14c1twb3MgKyAxXSA8PSBrYW5kKSBicmVhazsKICAgICAgICBzb2x2ZXIxX3BvbShzLCBiLCBwb3MgKyAxLCBudiwgcDEwLCBteHMsIHBhbSk7CiAgICB9Cn0KCnZvaWQgc29sdmVyMShzdHJpbmcmIHMsIGluZm8mIGIpewogICAgdW5vcmRlcmVkX21hcDxpbnQsIGJvb2w+IHBhbTsKCiAgICB2bCBwMTAobiArIDEsIDEpLCBteHMobiArIDEsIDApOwoKICAgIGZvcihpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKSBwMTBbaV0gPSBwMTBbaSAtIDFdICogMTA7CiAgICBmb3IoaW50IGkgPSBuIC0gMTsgaSA+PSAwOyBpLS0pewogICAgICAgIGludCB4ID0gaW50KHNbaV0gLSAnMCcpOwogICAgICAgIGlmKHNbaV0gPT0gJz8nKSB4ID0gOTsKICAgICAgICBteHNbaV0gPSB4ICogcDEwW24gLSBpIC0gMV0gKyBteHNbaSArIDFdOwogICAgfQoKICAgIHNvbHZlcjFfcG9tKHMsIGIsIDAsIDAsIHAxMCwgbXhzLCBwYW0pOwp9CgppbnQgc29sdmVyMl9wb20oaW50IHAsIGludCBxLCBpbmZvJiBhLCBpbmZvJiBiKXsKICAgIGxsIGxpbSA9IG1pbihhLm14IC8gcCwgYi5teCAvIHEpOwogICAgbGwgZG9sID0gbWF4KDFMTCwgbWF4KDFsbCAqIChhLm1uICsgcCAtIDEpIC8gcCwgMWxsICogKGIubW4gKyBxIC0gMSkgLyBxKSk7CgogICAgaWYobGltIDw9IGthbmQgfHwgZG9sID4gbGltKSByZXR1cm4gMDsKCiAgICBpbnQgcm96ID0gcCAqIHE7CiAgICBpZihkcC5zaXplKCkgPCByb3opewogICAgICAgIGRwLnJlc2l6ZShyb3opOwogICAgICAgIG5hc3QucmVzaXplKHJveik7CiAgICAgICAgb2R3LnJlc2l6ZShyb3osIDApOwogICAgfQogICAgYWt0eXcuY2xlYXIoKTsKICAgIG54dC5jbGVhcigpOwoKICAgIGFrdHl3LnBiKDApOwogICAgZHBbMF0gPSAwOwoKICAgIGxsIHBvdCA9IDE7CgogICAgZm9yKGludCBpID0gbiAtIDE7IGkgPj0gMDsgaS0tKXsKICAgICAgICBueHQuY2xlYXIoKTsKCiAgICAgICAgaWYoaXRlciA9PSBJTlRfTUFYKXsKICAgICAgICAgICAgZmlsbChhbGwob2R3KSwgMCk7CiAgICAgICAgICAgIGl0ZXIgPSAwOwogICAgICAgIH0KICAgICAgICBpdGVyKys7CgogICAgICAgIGZvcihpbnQgaiA6IGFrdHl3KXsKICAgICAgICAgICAgaW50IGNhID0gaiAvIHEsIGNiID0gaiAlIHE7CiAgICAgICAgICAgIGxsIHZhbCA9IGRwW2pdOwoKICAgICAgICAgICAgaWYodmFsID4gbGltKSBjb250aW51ZTsKCiAgICAgICAgICAgIGxsIGZpcnN0ID0gdmFsOwogICAgICAgICAgICBpZihmaXJzdCA8IGRvbCkgZmlyc3QgKz0gKGRvbCAtIGZpcnN0ICsgcG90IC0gMSkgLyBwb3QgKiBwb3Q7CiAgICAgICAgICAgIGlmKGZpcnN0ID4gbGltKSBjb250aW51ZTsKCiAgICAgICAgICAgIGxsIGxhc3QgPSB2YWwgKyAobGltIC0gdmFsKSAvIHBvdCAqIHBvdDsKICAgICAgICAgICAgaWYobGFzdCA8PSBrYW5kKSBjb250aW51ZTsKCiAgICAgICAgICAgIGZvcihpbnQgeiA9IDA7IHogPD0gOTsgeisrKXsKICAgICAgICAgICAgICAgIGludCB4ID0gcCAqIHogKyBjYSwgeSA9IHEgKiB6ICsgY2IsIGRhID0geCAlIDEwLCBkYiA9IHkgJSAxMDsKCiAgICAgICAgICAgICAgICBpZihhLnNbaV0gIT0gJz8nICYmIGEuc1tpXSAtICcwJyAhPSBkYSkgY29udGludWU7CiAgICAgICAgICAgICAgICBpZihiLnNbaV0gIT0gJz8nICYmIGIuc1tpXSAtICcwJyAhPSBkYikgY29udGludWU7CgogICAgICAgICAgICAgICAgaW50IG5hID0geCAvIDEwLCBuYiA9IHkgLyAxMCwgbCA9IG5hICogcSArIG5iOwogICAgICAgICAgICAgICAgbGwgbnYgPSB2YWwgKyB6ICogcG90OwogICAgICAgICAgICAgICAgaWYob2R3W2xdICE9IGl0ZXIpewogICAgICAgICAgICAgICAgICAgIG9kd1tsXSA9IGl0ZXI7CiAgICAgICAgICAgICAgICAgICAgbmFzdFtsXSA9IG52OwogICAgICAgICAgICAgICAgICAgIG54dC5wYihsKTsKICAgICAgICAgICAgICAgIH1lbHNlIG5hc3RbbF0gPSBtYXgobmFzdFtsXSwgbnYpOwogICAgICAgICAgICB9CiAgICAgICAgfQoKICAgICAgICBkcC5zd2FwKG5hc3QpOwogICAgICAgIGFrdHl3LnN3YXAobnh0KTsKCiAgICAgICAgaWYoYWt0eXcuZW1wdHkoKSkgcmV0dXJuIDA7CgogICAgICAgIHBvdCAqPSAxMDsKICAgIH0KCiAgICBpZihvZHdbMF0gIT0gaXRlcikgcmV0dXJuIDA7CiAgICByZXR1cm4gZHBbMF07Cn0KCgp2b2lkIHNvbHZlcjIoYm9vbCYgY3p5LCBpbmZvJiBhLCBpbmZvJiBiKXsKICAgIGNvbnN0IGludCBLID0gMTIwMDsKICAgIGludCB0ID0gbWF4KGEubXgsIGIubXgpOwogICAgY3p5ID0gZmFsc2U7CgogICAgYWt0eXcucmVzZXJ2ZSgyICogSyArIDUpOwogICAgbnh0LnJlc2VydmUoMiAqIEsgKyA1KTsKCiAgICBmb3IoaW50IGsgPSAxOyBrIDw9IEs7IGsrKyl7CiAgICAgICAgaWYodCAvIGsgPD0ga2FuZCl7CiAgICAgICAgICAgIGN6eSA9IHRydWU7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CgogICAgICAgIGZvcihpbnQgcCA9IDE7IHAgPD0gazsgcCsrKXsKICAgICAgICAgICAgaW50IHEgPSBrOwogICAgICAgICAgICBpZihtaW4oYS5teCAvIHAsIGIubXggLyBxKSA8PSBrYW5kKSBicmVhazsKICAgICAgICAgICAgaWYoX19nY2QocCwgcSkgIT0gMSkgY29udGludWU7CiAgICAgICAgICAgIGthbmQgPSBtYXgoa2FuZCwgc29sdmVyMl9wb20ocCwgcSwgYSwgYikpOwogICAgICAgICAgICBpZih0IC8gayA8PSBrYW5kKXsKICAgICAgICAgICAgICAgIGN6eSA9IHRydWU7CiAgICAgICAgICAgICAgICByZXR1cm47CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGZvcihpbnQgcSA9IDE7IHEgPCBrOyBxKyspewogICAgICAgICAgICBpbnQgcCA9IGs7CiAgICAgICAgICAgIGlmKG1pbihhLm14IC8gcCwgYi5teCAvIHEpIDw9IGthbmQpIGJyZWFrOwogICAgICAgICAgICBpZihfX2djZChwLCBxKSAhPSAxKSBjb250aW51ZTsKICAgICAgICAgICAga2FuZCA9IG1heChrYW5kLCBzb2x2ZXIyX3BvbShwLCBxLCBhLCBiKSk7CiAgICAgICAgICAgIGlmKHQgLyBrIDw9IGthbmQpewogICAgICAgICAgICAgICAgY3p5ID0gdHJ1ZTsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgaWYodCAvIChrICsgMSkgPD0ga2FuZCl7CiAgICAgICAgICAgIGN6eSA9IHRydWU7CiAgICAgICAgICAgIHJldHVybjsKICAgICAgICB9CiAgICB9Cn0KCmludCBtYWluKCl7CiAgICBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKDApOwogICAgY2luLnRpZSgwKTsKCiAgICBybmcuc2VlZCg2Nyk7CiAgICBjaW4gPj4gbiA+PiBBID4+IEI7CgogICAgaW5mbyBpYSA9IHByZXAoQSksIGliID0gcHJlcChCKTsKCiAgICBpZih0b3pzYW1lKCkpewogICAgICAgIGthbmQgPSB3c3BfbWF4KCk7CiAgICAgICAgaWYoa2FuZCA9PSBtaW4oaWEubXgsIGliLm14KSB8fCAyICoga2FuZCA+PSBtYXgoaWEubXgsIGliLm14KSl7CiAgICAgICAgICAgIGNvdXQgPDwga2FuZCA8PCAiXG4iOwogICAgICAgICAgICByZXR1cm4gMDsKICAgICAgICB9CiAgICB9CgogICAgaW50IHFhID0gaWxlX3phcChBKSwgcWIgPSBpbGVfemFwKEIpOwoKICAgIGlmKG1pbihxYSwgcWIpIDw9IDUpewogICAgICAgIHByZXBfcGllcndzemUoKTsKICAgICAgICBpZihxYSA8PSBxYikgc29sdmVyMShBLCBpYik7CiAgICAgICAgZWxzZSBzb2x2ZXIxKEIsIGlhKTsKCiAgICAgICAgY291dCA8PCBrYW5kIDw8ICJcbiI7CiAgICAgICAgcmV0dXJuIDA7CiAgICB9CgogICAgYm9vbCBjenk7CiAgICBzb2x2ZXIyKGN6eSwgaWEsIGliKTsKCiAgICBpZighY3p5KXsKICAgICAgICBwcmVwX3BpZXJ3c3plKCk7CiAgICAgICAgaWYocWEgPD0gcWIpIHNvbHZlcjEoQSwgaWIpOwogICAgICAgIGVsc2Ugc29sdmVyMShCLCBpYSk7CiAgICB9CgogICAgY291dCA8PCBrYW5kIDw8ICJcbiI7CiAgICByZXR1cm4gMDsKfQo=