Problem:
J - Unfair Game
Problem Statement
Rabbit Hanako and Fox Jiro are great friends going to JAG primary school. Today they decided to play the following game during the lunch break.
This game is played by two players with $N$ heaps of some number of stones. The players alternatively take their turn to play the game. Jiro is a kind gentleman, so he yielded the first turn to Hanako. In each turn, the player must take some stones, satisfying the following conditions:
If the player is Hanako, she must take between $1$ to $A$ stones, inclusive, from a heap.
If the player is Jiro, he must take between $1$ to $B$ stones, inclusive, from a heap.
The winner is the player who takes the last stone. Jiro thinks it is rude to go easy on her because he is a perfect gentleman. Therefore, he does him best. Of course, Hanako also does so.
Jiro is worried that he may lose the game. Being a cadet teacher working at JAG primary school as well as a professional competitive programmer, you should help him by programming. Your task is to write a program calculating the winner, assuming that they both play optimally.
Input
The first line contains three integers $N$, $A$, and $B$. $N$ ($1 \leq N \leq 10^5$) is the number of heaps. $A$ and $B$ ($1 \leq A, B \leq 10^9$) are the maximum numbers of stones that Hanako and Jiro can take in a turn, respectively. Then $N$ lines follow, each of which contains a single integer $S_i$ ($1 \leq S_i \leq 10^9$), representing the number of stones in the $i$-th heap at the beginning of the game.
Output
Output a line with "Hanako" if Hanako wins the game or "Jiro" in the other case.
Sample Input 1
3 5 4
3
6
12
Output for the Sample Input 1
Hanako
Sample Input 2
4 7 8
8
3
14
5
Output for the Sample Input 2
Jiro

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
 * @brief template
 */

bool Solve() {
    int N, A, B;
    cin >> N >> A >> B;
    vector<int> S(N);
    rep(i,0,N) cin >> S[i];
    if (A > B) {
        rep(i,0,N) {
            if (S[i] > B) return true;
        }
        int XOR = 0;
        rep(i,0,N) XOR ^= S[i];
        return (XOR != 0);
    }
    else if (A == B) {
        int XOR = 0;
        rep(i,0,N) XOR ^= (S[i] % (A+1));
        return (XOR != 0);
    }
    else {
        int COUNT = 0;
        rep(i,0,N) {
            if (S[i] > A) COUNT++;
        }
        if (COUNT >= 2) return false;
        else if (COUNT == 0) {
            int XOR = 0;
            rep(i,0,N) XOR ^= S[i];
            return (XOR != 0);
        }
        else {
            int ELSE = -1, XOR = 0;
            rep(i,0,N) {
                if (S[i] > A) ELSE = S[i];
                else XOR ^= S[i];
            }
            if (XOR > A) return false;
            if (1 <= ELSE-XOR && ELSE-XOR <= A) return true;
            return false;
        }
    }
}

int main() {
    cout << (Solve() ? "Hanako" : "Jiro") << endl;
}

/*
xooxxxxxxxxx
oxooxxxxxxxx
ooxooxxxxxxx
xooxxxxxxxxx
xxoxxxxxxxxx
xxxxxxxxxxxx

xooooooooooo
oxoooooooooo
ooxooooooooo
oooo
*/
accuracy: 1
time_ms: 20
memory_kb: 3504
final_rank: 4

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
    ll N,A,B,X=0;
    cin>>N>>A>>B;
    vector<ll> V(N);
    for(auto &v:V)cin>>v;
    sort(V.begin(),V.end());
    if(A==B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else if(A>=B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0||V.back()>=B+1){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else{
        for(auto v:V)X=(X^(v%(A+1)));
        if(N>1&&V[N-2]>=A+1){
            cout<<"Jiro"<<endl;
        }
        else if(V.back()<=A){
            cout<<(X!=0?"Hanako":"Jiro")<<endl;
        }
        else {
            ll d=X^(V.back()%(A+1));
            cout<<(X!=d&&d<=A&&V.back()-d<=A?"Hanako":"Jiro")<<endl;
        }
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3876
final_rank: 6

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
    ll N,A,B,X=0;
    cin>>N>>A>>B;
    vector<ll> V(N);
    for(auto &v:V)cin>>v;
    sort(V.begin(),V.end());
    if(A==B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else if(A>=B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0||V.back()>=B+1){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else{
        for(auto v:V)X=(X^(v%(A+1)));
        if(N>1&&V[N-2]>=A+1){
            cout<<"Jiro"<<endl;
        }
        else if(V.back()<=A){
            cout<<(X!=0?"Hanako":"Jiro")<<endl;
        }
        else {
            ll d=X^(V.back()%(A+1));
            cout<<(X!=d&&d<=A&&X-d<=A?"Hanako":"Jiro")<<endl;
        }
    }
}
accuracy: 0.6593406593406593
time_ms: 20
memory_kb: 3876
final_rank: 14

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
    ll N,A,B,X=0;
    cin>>N>>A>>B;
    vector<ll> V(N);
    for(auto &v:V)cin>>v;
    sort(V.begin(),V.end());
    if(A==B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else if(A>=B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0||V.back()>=B+1){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else{
        for(auto v:V)X=(X^(v%(A+1)));
        if(N>1&&V[N-2]>=A+1){
            cout<<"Jiro"<<endl;
        }
        else if(V.back()<=A){
            cout<<(X!=0?"Hanako":"Jiro")<<endl;
        }
        else {
            ll d=X^(V.back()%(A+1));
            cout<<(d<=A&&X-d<=A?"Hanako":"Jiro")<<endl;
        }
    }
}
accuracy: 0.6483516483516484
time_ms: 20
memory_kb: 3908
final_rank: 16

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
    ll N,A,B,X=0;
    cin>>N>>A>>B;
    vector<ll> V(N);
    for(auto &v:V)cin>>v;
    sort(V.begin(),V.end());
    if(A==B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else if(A>=B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0||V.back()>=B+1){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else{
        for(auto v:V)X=(X^(v%(A+1)));
        if(N>1&&V[N-2]>=A+1){
            cout<<"Jiro"<<endl;
        }
        else if(V.back()<=A){
            cout<<(X!=0?"Hanako":"Jiro")<<endl;
        }
        else {
            ll d=X^(V.back());
            cout<<(d<=A&&X-d<=A?"Hanako":"Jiro")<<endl;
        }
    }
}
accuracy: 0.5494505494505495
time_ms: 20
memory_kb: 3904
final_rank: 18

code_snippet: #include<bits/stdc++.h>
using namespace std;
using ll = long long;

int main() {
    ll N,A,B,X=0;
    cin>>N>>A>>B;
    vector<ll> V(N);
    for(auto &v:V)cin>>v;
    sort(V.begin(),V.end());
    if(A==B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else if(A>=B){
        for(auto v:V)X=(X^(v%(B+1)));
        if(X!=0||V.back()>=B+1){
            cout<<"Hanako"<<endl;
        }
        else cout<<"Jiro"<<endl;
    }
    else{
        for(auto v:V)X=(X^(v%(A+1)));
        if(N>1&&V[N-2]>=A+1){
            cout<<"Jiro"<<endl;
        }
        else if(V.back()<=A){
            cout<<(X==0?"Hanako":"Jiro")<<endl;
        }
        else {
            ll d=X^(V.back());
            cout<<(d<=A&&X-d<=A?"Hanako":"Jiro")<<endl;
        }
    }
}
accuracy: 0.5274725274725275
time_ms: 20
memory_kb: 3904
final_rank: 20

code_snippet: #pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long int ll;
typedef unsigned long long int ull;

mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) { return (ull)rng() % B; }

int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    int n, a, b;
    cin >> n >> a >> b;
    vector<int> s(n);
    for (int i = 0; i < n; ++i) {
        cin >> s[i];
    }
    int minG = 0;
    for (int i = 0; i < n; ++i) {
        minG ^= (s[i] % (min(a, b) + 1));
    }
    if (a == b) {
        if (minG) {
            cout << "Hanako" << endl;
        } else {
            cout << "Jiro" << endl;
        }
    } else if (a > b) {
        if (minG) {
            cout << "Hanako" << endl;
        } else {
            bool ok = false;
            for (int i = 0; i < n; ++i) {
                if (s[i] >= b + 1) ok = true;
            }
            if (ok) {
                cout << "Hanako" << endl;
            } else {
                cout << "Jiro" << endl;
            }
        }
    } else {
        // a+1以上の山を相手に渡してはいけない
        // そのうえXORを0にできたら先手勝ち
        sort(s.rbegin(), s.rend());
        int g = 0;
        for (int i = 0; i < n; ++i) {
            g ^= s[i];
        }
        if ((s.size() > 1 and s[1] >= a + 1) or g == 0) {
            cout << "Jiro" << endl;
        } else {
            if (s[0] <= a) {
                cout << "Hanako" << endl;
            } else {
                g ^= s[0];
                if (g < s[0] and (s[0] - g) <= a and g <= a) {
                    cout << "Hanako" << endl;
                } else {
                    cout << "Jiro" << endl;
                }
            }
        }
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3636
final_rank: 1

code_snippet: #include<bits/stdc++.h>
using namespace std;
int main(){
    int n, a, b, s, axo=0, bxo=0, oth=0, ma=0;
    vector<int> vec;
    cin >> n >> a >> b;
    for(int i=0;i<n;i++){
        cin >> s;
        axo ^= s%(a+1);
        bxo ^= s%(b+1);
        ma = max(ma, s);
        if(s > a) vec.push_back(s);
        else oth ^= s;
    }
    if(a>=b){
        if(bxo!=0 || a>b && ma>b) cout << "Hanako" << endl;
        else cout << "Jiro" << endl;
    } else{
        if(vec.size()==0 && axo!=0 || vec.size()==1 && oth<=a && vec[0]-oth<=a) cout << "Hanako" << endl;
        else cout << "Jiro" << endl;
    }
    return(0);
}
accuracy: 1
time_ms: 20
memory_kb: 3432
final_rank: 3

code_snippet: #include<bits/stdc++.h>
using namespace std;
int main(){
    int n, a, b, s[100010], axo=0, bxo=0, ma=0;
    vector<int> vec;
    cin >> n >> a >> b;
    for(int i=0;i<n;i++){
        cin >> s[i];
        axo ^= s[i]%(a+1);
        bxo ^= s[i]%(b+1);
        ma = max(ma, s[i]);
        if(s[i] > a) vec.push_back(s[i]);
    }
    if(a>=b){
        if(bxo!=0) cout << "Hanako" << endl;
        else if(a>b && ma>b) cout << "Hanako" << endl;
        else cout << "Jiro" << endl;
    } else{
        if(vec.size()==0){
            if(axo!=0) cout << "Hanako" << endl;
            else cout << "Jiro" << endl;
        }
        else if(vec.size()==1){
            int oth=0;
            for(int i=0;i<n;i++){
                if(s[i]<vec[0]) oth ^= s[i]%(a+1);
            }
            if(oth<=a && vec[0]-oth<=a) cout << "Hanako" << endl;
            else cout << "Jiro" << endl;
        }
        else cout << "Jiro" << endl;
    }
    return(0);
}
accuracy: 1
time_ms: 20
memory_kb: 3920
final_rank: 8

code_snippet: #include<bits/stdc++.h>
using namespace std;
int main(){
    int n, a, b, s[100010], axo=0, bxo=0, ma=0;
    vector<int> vec;
    cin >> n >> a >> b;
    for(int i=0;i<n;i++){
        cin >> s[i];
        axo ^= s[i]%(a+1);
        bxo ^= s[i]%(b+1);
        ma = max(ma, s[i]);
        if(s[i] > a) vec.push_back(s[i]);
    }
    axo %= (a+1);
    bxo %= (b+1);
    if(a>=b){
        if(bxo!=0) cout << "Hanako" << endl;
        else if(a>b && ma>b) cout << "Hanako" << endl;
        else cout << "Jiro" << endl;
    } else{
        if(vec.size()==0){
            if(axo!=0) cout << "Hanako" << endl;
            else cout << "Jiro" << endl;
        }
        else if(vec.size()==1){
            int oth=0;
            for(int i=0;i<n;i++){
                if(s[i]<vec[0]) oth ^= s[i]%(a+1);
            }
            oth %= a+1;
            if(vec[0]-oth<=a) cout << "Hanako" << endl;
            else cout << "Jiro" << endl;
        }
        else cout << "Jiro" << endl;
    }
    return(0);
}
accuracy: 0.8461538461538461
time_ms: 20
memory_kb: 3656
final_rank: 9

code_snippet: #include<bits/stdc++.h>
using namespace std;
int main(){
    int n, a, b, s[100010], axo=0, bxo=0, ma=0;
    vector<int> vec;
    cin >> n >> a >> b;
    for(int i=0;i<n;i++){
        cin >> s[i];
        axo ^= s[i]%(a+1);
        bxo ^= s[i]%(b+1);
        ma = max(ma, s[i]);
        if(s[i] > a) vec.push_back(s[i]);
    }
    if(a>=b){
        if(bxo!=0) cout << "Hanako" << endl;
        else if(a>b && ma>b) cout << "Hanako" << endl;
        else cout << "Jiro" << endl;
    } else{
        if(vec.size()==0){
            if(axo!=0) cout << "Hanako" << endl;
            else cout << "Jiro" << endl;
        }
        else if(vec.size()==1){
            int oth=0;
            for(int i=0;i<n;i++){
                if(s[i]<vec[0]) oth ^= s[i]%(a+1);
            }
            if(vec[0]-oth<=a) cout << "Hanako" << endl;
            else cout << "Jiro" << endl;
        }
        else cout << "Jiro" << endl;
    }
    return(0);
}
accuracy: 0.7252747252747253
time_ms: 20
memory_kb: 3656
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
int main(){
    int n, a, b, s, axo=0, bxo=0, ma=0;
    vector<int> vec;
    cin >> n >> a >> b;
    for(int i=0;i<n;i++){
        cin >> s;
        axo ^= s%(a+1);
        bxo ^= s%(b+1);
        ma = max(ma, s);
        if(s > a) vec.push_back(s);
    }
    if(a==b){
        
    }
    if(a>=b){
        if(bxo!=0) cout << "Hanako" << endl;
        else if(a>b && ma>b) cout << "Hanako" << endl;
        else cout << "Jiro" << endl;
    } else{
        if(vec.size()==0){
            if(axo!=0) cout << "Hanako" << endl;
            else cout << "Jiro" << endl;
        }
        else if(vec.size()==1 && vec[0]-(vec[0]-axo)<=a) cout << "Hanako" << endl;
        else cout << "Jiro" << endl;
    }
    return(0);
}
accuracy: 0.6373626373626373
time_ms: 20
memory_kb: 3260
final_rank: 17

code_snippet: #include<bits/stdc++.h>
using namespace std;
int main(){
    int n, a, b, s, axo=0, bxo=0, ma=0;
    vector<int> vec;
    cin >> n >> a >> b;
    for(int i=0;i<n;i++){
        cin >> s;
        axo ^= s%(a+1);
        bxo ^= s%(b+1);
        ma = max(ma, s);
        if(s > a) vec.push_back(s);
    }
    if(a==b){
        
    }
    if(a>=b){
        if(bxo!=0) cout << "Hanako" << endl;
        else if(a>b && ma>b) cout << "Hanako" << endl;
        else cout << "Jiro" << endl;
    } else{
        if(vec.size()==0){
            if(axo!=0) cout << "Hanako" << endl;
            else cout << "Jiro" << endl;
        }
        if(vec.size()==1 && vec[0]-(vec[0]-axo)<=a) cout << "Hanako" << endl;
        else cout << "Jiro" << endl;
    }
    return(0);
}
accuracy: 0.5274725274725275
time_ms: 20
memory_kb: 3268
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

bool solve(int N, int A, int B, const vector<int>& S) {
	int C = min(A, B);
	int grundy = 0;
	for (int i = 0; i < N; i++) {
		grundy ^= S[i] % (C + 1);
	}
	if (A > B) {
		if (grundy != 0) {
			return true;
		}
		for (int i = 0; i < N; i++) {
			if (S[i] >= B + 1) {
				return true;
			}
		}
		return false;
	}
	if (A < B) {
		if (grundy == 0) {
			return false;
		}
		vector<int> poses;
		for (int i = 0; i < N; i++) {
			if (S[i] >= A + 1) {
				poses.push_back(i);
			}
		}
		if (poses.size() >= 2) {
			return false;
		}
		if (poses.size() == 0) {
			return true;
		}
		int pos = poses[0];
		int target = grundy ^ (S[pos] % (C + 1));
		return (target <= C && S[pos] - target <= A);
	}
	return (grundy != 0);
}

int main() {
	int N, A, B;
	cin >> N >> A >> B;
	vector<int> S(N);
	for (int i = 0; i < N; i++) {
		cin >> S[i];
	}
	bool ans = solve(N, A, B, S);
	cout << (ans ? "Hanako" : "Jiro") << endl;
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3788
final_rank: 5

code_snippet: /*	author:  Kite_kuma
	created: 2021.11.03 09:47:45 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

template <class T = long long>
struct edge {
	T len;
	int from;
	int to;
	bool operator<(const edge a) const {
		if(len != a.len) return len < a.len;
		if(from != a.from) return from < a.from;
		return to < a.to;
	}
	bool operator>(const edge a) const {
		if(len != a.len) return len > a.len;
		if(from != a.from) return from > a.from;
		return to > a.to;
	}
};
template <class T = long long>
struct graph {	// 0-indexed
	T const INF = numeric_limits<T>::max() / 3;
	vector<vector<edge<T>>> edges;
	int ver;

	// constructor
	graph() = default;
	graph(int vertex) : ver(vertex), edges(vertex) {}

	//辺の追加 (0-indexed)
	void update(int from, int to, T len = 1, bool direction = 1) {	// checked
		edge<T> e;
		e.len = len;
		e.from = from;
		e.to = to;
		edges[from].push_back(e);
		if(!direction) {
			swap(e.to, e.from);
			edges[to].push_back(e);
		}
	}

	//入力受取 (1-indexed)
	void input(int edge_num, bool direction = false, bool weight = false, int index = 1) {	// checked
		for(int i = 0; i < edge_num; i++) {
			int a;
			int b;
			cin >> a >> b;
			a -= index;
			b -= index;
			T c;
			if(weight)
				cin >> c;
			else
				c = 1;
			update(a, b, c, direction);
		}
	}

	// 辺の長さを全て1とみたときの単一始点最短経路 (無理なときはINF)
	vector<T> bfs(int start) {	// checked
		// https://atcoder.jp/contests/abc007/submissions/me
		vector<T> ret(ver, INF);
		queue<int> q;
		q.push(start);
		ret[start] = 0;
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(ret[e.to] != INF) continue;
				q.push(e.to);
				ret[e.to] = ret[now] + 1;
			}
		}
		return ret;
	}

	vector<T> zero_one_bfs(int start) {	 // checked
		vector<T> ret(ver, INF);
		deque<int> deq;
		deq.push_back(start);
		ret[start] = 0;
		while(!deq.empty()) {
			int now = deq.front();
			deq.pop_front();
			for(auto &e : edges[now]) {
				if(chmin(ret[e.to], ret[now] + e.len)) {
					if(e.len)
						deq.push_back(e.to);
					else
						deq.push_front(e.to);
				}
			}
		}
		return ret;
	}

	//長さが負のpathがないときの単一始点最短経路<vll> O((ver)log(ver)+(edge))
	vector<T> dijkstra(int start) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_A/judge/4817136/C++14
		vector<T> ret(ver, (T)INF);													  //{dist,place}
		priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> p;  //{dist,place}
		p.push({0, start});
		ret[start] = 0;

		while(!p.empty()) {
			T dist = p.top().first;
			int place = p.top().second;
			p.pop();
			if(ret[place] < dist) continue;
			for(auto &next : edges[place]) {
				int nextplace = next.to;
				T dis = next.len;
				if(ret[nextplace] > dist + dis) {
					ret[nextplace] = dist + dis;
					p.push({ret[nextplace], nextplace});
				}
			}
		}
		return ret;
	}

	//単一始点最短経路 O((ver)*(edge))
	//辿り着けないとき ret[i] = INF;
	//ある頂点までのコストが無限に小さくなり得るとき→ ret[i] = -INF;
	vector<T> BellmanFord(int start) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_B/judge/4817139/C++14
		vector<T> ret(ver, INF);
		ret[start] = 0;
		for(int loop = 0; loop < ver - 1; loop++) {
			for(int v = 0; v < ver; v++) {
				if(ret[v] == INF) continue;
				for(auto &e : edges[v]) {
					ret[e.to] = min(ret[e.to], ret[v] + e.len);
				}
			}
		}

		//無限降下点の検索
		queue<int> q;
		vector<bool> chk(ver, 0);
		for(int v = 0; v < ver; v++) {
			if(ret[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(ret[e.to] > ret[v] + e.len) {
					ret[e.to] = ret[v] + e.len;
					if(!chk[e.to]) {
						q.push(e.to);
						chk[e.to] = 1;
					}
				}
			}
		}
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					q.push(e.to);
				}
			}
		}
		for(int i = 0; i < ver; i++)
			if(chk[i]) ret[i] = -INF;

		return ret;
	}

	//閉路に含まれない頂点列挙
	//要素数がver未満なら閉路が存在、そうでなければ閉路は存在しない
	vector<int> topo_sort() {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_B/judge/4817106/C++14
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_A/judge/4817110/C++14
		vector<int> num_input(ver);
		// 入次数
		for(int i = 0; i < ver; i++) {
			for(auto e : edges[i]) {
				num_input[e.to]++;
			}
		}
		// 入次数が0のノードをqueueで管理する
		queue<int> que;
		for(int i = 0; i < ver; i++) {
			if(num_input[i] == 0) {
				que.push(i);
			}
		}
		vector<int> ans;
		while(!que.empty()) {
			auto node = que.front();
			que.pop();
			ans.push_back(node);
			// 頂点の削除
			for(auto e : edges[node]) {
				num_input[e.to]--;
				// 行き先の入次数が0になったらqueueに追加
				if(num_input[e.to] == 0) {
					que.push(e.to);
				}
			}
		}
		return ans;
	}

	//{{端点、端点},直径の大きさ}
	pair<pair<int, int>, T> DiameterOfTree(bool weigh = true) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_A/judge/4817099/C++14
		vector<T> vec;
		vec = weigh ? dijkstra(0) : bfs(0);
		int v1 = -1;
		T dia = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				dia = vec[i];
				v1 = i;
			}

		vec = weigh ? dijkstra(v1) : bfs(v1);
		dia = -1;
		int v2 = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				v2 = i;
				dia = vec[i];
			}

		pair<pair<int, int>, T> ans = {{v1, v2}, dia};
		return ans;
	}

	//無向木構造を根から葉に伸びる有向木構造に書き換える
	graph<T> RootToLeaf(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(now, e.to, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//無向木構造を葉から根に伸びる有向木構造に書き換える
	graph<T> LeafToRoot(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(e.to, now, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		ret.update(root, root, 0);
		return ret;
	}

	// LeafToRootのvector版.par[i]=iの親の頂点
	vector<int> par(int root) {	 // 0-indexed
		vector<int> ret(ver, -1);
		ret[root] = root;  // rootの親はroot
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to] != -1) continue;
				ret[e.to] = now;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	vector<edge<T>> ParentAndDistance(int root) {  // 0-indexed
		vector<edge<T>> ret(ver);
		for(int i = 0; i < ver; i++) ret[i].to = -1;
		ret[root].to = root;  // rootの親はroot
		ret[root].len = 0;	  // rootの親との距離は0
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to].to != -1) continue;
				ret[e.to].to = now;
				ret[e.to].len = e.len;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//隣接sheet.主にwarshall用
	vector<vector<T>> GraphArray(void) {  // chkecked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_C/judge/4817090/C++14
		vector<vector<T>> ret(ver, vector<T>(ver, INF));
		for(int from = 0; from < ver; from++) {
			for(auto &e : edges[from]) {
				ret[from][e.to] = e.len;
			}
			ret[from][from] = 0;
		}
		return ret;
	}

	graph<T> Prim(bool direction = 0, int start = 0) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_2_A/judge/4817129/C++14
		graph<T> ret(ver);
		priority_queue<edge<T>, vector<edge<T>>, greater<edge<T>>> p;
		for(auto &e : edges[start]) {
			p.push(e);
		}
		vector<bool> chk(ver, 0);
		chk[start] = 1;
		while(!p.empty()) {
			auto ed = p.top();
			p.pop();
			if(chk[ed.to]) continue;
			chk[ed.to] = 1;
			ret.update(ed.from, ed.to, ed.len, direction);
			for(auto &e : edges[ed.to]) {
				p.push(e);
			}
		}
		return ret;
	}

	//各頂点を根としたときの木の高さ
	vector<T> height(int start = 0) {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_B/judge/4817082/C++14
		vector<T> fir(ver, -1), sec(ver, -1);
		function<T(int, int)> dfs = [&](int now, int par) {
			T f = 0, s = 0;	 // startを根としたときのnowからの深さ1番目、2番目
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				s = max(s, dfs(e.to, now) + e.len);
				if(f < s) swap(f, s);
			}
			sec[now] = s;
			return fir[now] = f;
		};
		dfs(start, -1);
		function<void(int, int, T, T, T)> sol = [&](int now, int par, T parf, T pars, T parlen) {
			if(fir[now] + parlen == parf) parf = pars;
			sec[now] = max(sec[now], parf + parlen);
			if(fir[now] < sec[now]) swap(fir[now], sec[now]);
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				sol(e.to, now, fir[now], sec[now], e.len);
			}
			return;
		};
		sol(start, -1, -1, -1, -1);
		return fir;
	}

	//全方位木DP
	//マージ関数、上に送るための関数、単位元、はじめの根
	// 関数はstd::functionで渡す
	template <class U>
	vector<U> ReRootingDP(U &unit, function<U(U, U)> &merge, function<U(int, U, T)> &send, int root = 0) {
		auto tr = RootToLeaf(root);
		vector<vector<U>> v(ver);
		vector<U> ret(ver);	 //求める答

		function<U(int)> treeDP = [&](int now) {
			U res = unit;
			vector<U> vec;
			for(auto &e : tr.edges[now]) {
				U u = send(e.to, treeDP(e.to), e.len);
				v[now].push_back(u);
				res = merge(res, u);
			}
			return res;
		};
		treeDP(root);

		function<void(int, U, int, T)> rerooting = [&](int now, U ans_par, int par, T len) {
			if(now != root) ans_par = send(par, ans_par, len);
			int sz = v[now].size();
			vector<U> data_front(sz + 1), data_back(sz + 1);
			data_front[0] = data_back[sz] = unit;
			for(int i = 0; i < sz; i++) {
				data_front[i + 1] = merge(data_front[i], v[now][i]);
				data_back[sz - i - 1] = merge(v[now][sz - i - 1], data_back[sz - i]);
			}
			for(int i = 0; i < sz; i++) {
				auto nxtans = merge(ans_par, merge(data_front[i], data_back[i + 1]));
				rerooting(tr.edges[now][i].to, nxtans, now, tr.edges[now][i].len);
			}
			ret[now] = merge(ans_par, data_front[sz]);
			return;
		};
		rerooting(root, unit, root, 0);

		return ret;
	}

	// HL分解
};

// 強連結成分分解
struct SCC {
	graph<int> ng, rg;	// normal graph, reversed graph
	vector<int> compo;	// compo[i] = 新グラフでiが属する頂点集合番号
	vector<int> order;
	vector<bool> used;
	graph<int> ret;
	// g:元のグラフ, ret:強連結成分分解後のグラフ

	template <class T>
	SCC(graph<T> &g) : ng(g.ver), rg(g.ver), compo(g.ver, -1), used(g.ver, false) {
		for(int from = 0; from < g.ver; from++) {
			for(auto &e : g.edges[from]) {
				ng.update(e.from, e.to, 1, 1);
				rg.update(e.to, e.from, 1, 1);
			}
		}

		for(int i = 0; i < ng.ver; i++) dfs(i);
		reverse(order.begin(), order.end());
		int group = 0;
		for(auto i : order)
			if(compo[i] == -1) rdfs(i, group), group++;
		ret.edges.resize(group);
		for(int i = 0; i < g.ver; i++) {
			for(auto &e : g.edges[i]) {
				int s = compo[i], t = compo[e.to];
				if(s != t) ret.update(s, t, 1, 1);
			}
		}
	}

	int operator[](int k) { return compo[k]; }

	void dfs(int now) {
		if(used[now]) return;
		used[now] = true;
		for(auto &e : ng.edges[now]) dfs(e.to);
		order.push_back(now);
	}

	void rdfs(int now, int count) {
		if(compo[now] != -1) return;
		compo[now] = count;
		for(auto &e : rg.edges[now]) rdfs(e.to, count);
	}
};

#pragma endregion

bool nim(vll s) {
	ll g = 0;
	foa(t, s) g ^= t;
	return bool(g);
}

bool fairgame(vll s, ll take) {
	ll g = 0;
	foa(t, s) g ^= t % (take + 1);
	return bool(g);
}

bool solve(int n) {
	ll a, b;
	cin >> a >> b;
	VEC(ll, s, n);
	sort(all(s));
	if(s.back() <= min(a, b)) return nim(s);
	if(a == b) return fairgame(s, a);
	if(a > b) return true;
	if(n > 1 && s[n - 2] > a) return false;
	ll g = 0;
	rep(i, n - 1) { g ^= s[i]; }
	ll musttake = s.back() - g;
	return 0 < musttake && musttake <= a && g <= a;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n && n) {
		cout << (solve(n) ? "Hanako" : "Jiro") << dl;
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 4624
final_rank: 2

code_snippet: /*	author:  Kite_kuma
	created: 2021.11.03 09:47:45 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

template <class T = long long>
struct edge {
	T len;
	int from;
	int to;
	bool operator<(const edge a) const {
		if(len != a.len) return len < a.len;
		if(from != a.from) return from < a.from;
		return to < a.to;
	}
	bool operator>(const edge a) const {
		if(len != a.len) return len > a.len;
		if(from != a.from) return from > a.from;
		return to > a.to;
	}
};
template <class T = long long>
struct graph {	// 0-indexed
	T const INF = numeric_limits<T>::max() / 3;
	vector<vector<edge<T>>> edges;
	int ver;

	// constructor
	graph() = default;
	graph(int vertex) : ver(vertex), edges(vertex) {}

	//辺の追加 (0-indexed)
	void update(int from, int to, T len = 1, bool direction = 1) {	// checked
		edge<T> e;
		e.len = len;
		e.from = from;
		e.to = to;
		edges[from].push_back(e);
		if(!direction) {
			swap(e.to, e.from);
			edges[to].push_back(e);
		}
	}

	//入力受取 (1-indexed)
	void input(int edge_num, bool direction = false, bool weight = false, int index = 1) {	// checked
		for(int i = 0; i < edge_num; i++) {
			int a;
			int b;
			cin >> a >> b;
			a -= index;
			b -= index;
			T c;
			if(weight)
				cin >> c;
			else
				c = 1;
			update(a, b, c, direction);
		}
	}

	// 辺の長さを全て1とみたときの単一始点最短経路 (無理なときはINF)
	vector<T> bfs(int start) {	// checked
		// https://atcoder.jp/contests/abc007/submissions/me
		vector<T> ret(ver, INF);
		queue<int> q;
		q.push(start);
		ret[start] = 0;
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(ret[e.to] != INF) continue;
				q.push(e.to);
				ret[e.to] = ret[now] + 1;
			}
		}
		return ret;
	}

	vector<T> zero_one_bfs(int start) {	 // checked
		vector<T> ret(ver, INF);
		deque<int> deq;
		deq.push_back(start);
		ret[start] = 0;
		while(!deq.empty()) {
			int now = deq.front();
			deq.pop_front();
			for(auto &e : edges[now]) {
				if(chmin(ret[e.to], ret[now] + e.len)) {
					if(e.len)
						deq.push_back(e.to);
					else
						deq.push_front(e.to);
				}
			}
		}
		return ret;
	}

	//長さが負のpathがないときの単一始点最短経路<vll> O((ver)log(ver)+(edge))
	vector<T> dijkstra(int start) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_A/judge/4817136/C++14
		vector<T> ret(ver, (T)INF);													  //{dist,place}
		priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> p;  //{dist,place}
		p.push({0, start});
		ret[start] = 0;

		while(!p.empty()) {
			T dist = p.top().first;
			int place = p.top().second;
			p.pop();
			if(ret[place] < dist) continue;
			for(auto &next : edges[place]) {
				int nextplace = next.to;
				T dis = next.len;
				if(ret[nextplace] > dist + dis) {
					ret[nextplace] = dist + dis;
					p.push({ret[nextplace], nextplace});
				}
			}
		}
		return ret;
	}

	//単一始点最短経路 O((ver)*(edge))
	//辿り着けないとき ret[i] = INF;
	//ある頂点までのコストが無限に小さくなり得るとき→ ret[i] = -INF;
	vector<T> BellmanFord(int start) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_B/judge/4817139/C++14
		vector<T> ret(ver, INF);
		ret[start] = 0;
		for(int loop = 0; loop < ver - 1; loop++) {
			for(int v = 0; v < ver; v++) {
				if(ret[v] == INF) continue;
				for(auto &e : edges[v]) {
					ret[e.to] = min(ret[e.to], ret[v] + e.len);
				}
			}
		}

		//無限降下点の検索
		queue<int> q;
		vector<bool> chk(ver, 0);
		for(int v = 0; v < ver; v++) {
			if(ret[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(ret[e.to] > ret[v] + e.len) {
					ret[e.to] = ret[v] + e.len;
					if(!chk[e.to]) {
						q.push(e.to);
						chk[e.to] = 1;
					}
				}
			}
		}
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					q.push(e.to);
				}
			}
		}
		for(int i = 0; i < ver; i++)
			if(chk[i]) ret[i] = -INF;

		return ret;
	}

	//閉路に含まれない頂点列挙
	//要素数がver未満なら閉路が存在、そうでなければ閉路は存在しない
	vector<int> topo_sort() {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_B/judge/4817106/C++14
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_A/judge/4817110/C++14
		vector<int> num_input(ver);
		// 入次数
		for(int i = 0; i < ver; i++) {
			for(auto e : edges[i]) {
				num_input[e.to]++;
			}
		}
		// 入次数が0のノードをqueueで管理する
		queue<int> que;
		for(int i = 0; i < ver; i++) {
			if(num_input[i] == 0) {
				que.push(i);
			}
		}
		vector<int> ans;
		while(!que.empty()) {
			auto node = que.front();
			que.pop();
			ans.push_back(node);
			// 頂点の削除
			for(auto e : edges[node]) {
				num_input[e.to]--;
				// 行き先の入次数が0になったらqueueに追加
				if(num_input[e.to] == 0) {
					que.push(e.to);
				}
			}
		}
		return ans;
	}

	//{{端点、端点},直径の大きさ}
	pair<pair<int, int>, T> DiameterOfTree(bool weigh = true) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_A/judge/4817099/C++14
		vector<T> vec;
		vec = weigh ? dijkstra(0) : bfs(0);
		int v1 = -1;
		T dia = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				dia = vec[i];
				v1 = i;
			}

		vec = weigh ? dijkstra(v1) : bfs(v1);
		dia = -1;
		int v2 = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				v2 = i;
				dia = vec[i];
			}

		pair<pair<int, int>, T> ans = {{v1, v2}, dia};
		return ans;
	}

	//無向木構造を根から葉に伸びる有向木構造に書き換える
	graph<T> RootToLeaf(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(now, e.to, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//無向木構造を葉から根に伸びる有向木構造に書き換える
	graph<T> LeafToRoot(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(e.to, now, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		ret.update(root, root, 0);
		return ret;
	}

	// LeafToRootのvector版.par[i]=iの親の頂点
	vector<int> par(int root) {	 // 0-indexed
		vector<int> ret(ver, -1);
		ret[root] = root;  // rootの親はroot
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to] != -1) continue;
				ret[e.to] = now;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	vector<edge<T>> ParentAndDistance(int root) {  // 0-indexed
		vector<edge<T>> ret(ver);
		for(int i = 0; i < ver; i++) ret[i].to = -1;
		ret[root].to = root;  // rootの親はroot
		ret[root].len = 0;	  // rootの親との距離は0
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to].to != -1) continue;
				ret[e.to].to = now;
				ret[e.to].len = e.len;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//隣接sheet.主にwarshall用
	vector<vector<T>> GraphArray(void) {  // chkecked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_C/judge/4817090/C++14
		vector<vector<T>> ret(ver, vector<T>(ver, INF));
		for(int from = 0; from < ver; from++) {
			for(auto &e : edges[from]) {
				ret[from][e.to] = e.len;
			}
			ret[from][from] = 0;
		}
		return ret;
	}

	graph<T> Prim(bool direction = 0, int start = 0) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_2_A/judge/4817129/C++14
		graph<T> ret(ver);
		priority_queue<edge<T>, vector<edge<T>>, greater<edge<T>>> p;
		for(auto &e : edges[start]) {
			p.push(e);
		}
		vector<bool> chk(ver, 0);
		chk[start] = 1;
		while(!p.empty()) {
			auto ed = p.top();
			p.pop();
			if(chk[ed.to]) continue;
			chk[ed.to] = 1;
			ret.update(ed.from, ed.to, ed.len, direction);
			for(auto &e : edges[ed.to]) {
				p.push(e);
			}
		}
		return ret;
	}

	//各頂点を根としたときの木の高さ
	vector<T> height(int start = 0) {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_B/judge/4817082/C++14
		vector<T> fir(ver, -1), sec(ver, -1);
		function<T(int, int)> dfs = [&](int now, int par) {
			T f = 0, s = 0;	 // startを根としたときのnowからの深さ1番目、2番目
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				s = max(s, dfs(e.to, now) + e.len);
				if(f < s) swap(f, s);
			}
			sec[now] = s;
			return fir[now] = f;
		};
		dfs(start, -1);
		function<void(int, int, T, T, T)> sol = [&](int now, int par, T parf, T pars, T parlen) {
			if(fir[now] + parlen == parf) parf = pars;
			sec[now] = max(sec[now], parf + parlen);
			if(fir[now] < sec[now]) swap(fir[now], sec[now]);
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				sol(e.to, now, fir[now], sec[now], e.len);
			}
			return;
		};
		sol(start, -1, -1, -1, -1);
		return fir;
	}

	//全方位木DP
	//マージ関数、上に送るための関数、単位元、はじめの根
	// 関数はstd::functionで渡す
	template <class U>
	vector<U> ReRootingDP(U &unit, function<U(U, U)> &merge, function<U(int, U, T)> &send, int root = 0) {
		auto tr = RootToLeaf(root);
		vector<vector<U>> v(ver);
		vector<U> ret(ver);	 //求める答

		function<U(int)> treeDP = [&](int now) {
			U res = unit;
			vector<U> vec;
			for(auto &e : tr.edges[now]) {
				U u = send(e.to, treeDP(e.to), e.len);
				v[now].push_back(u);
				res = merge(res, u);
			}
			return res;
		};
		treeDP(root);

		function<void(int, U, int, T)> rerooting = [&](int now, U ans_par, int par, T len) {
			if(now != root) ans_par = send(par, ans_par, len);
			int sz = v[now].size();
			vector<U> data_front(sz + 1), data_back(sz + 1);
			data_front[0] = data_back[sz] = unit;
			for(int i = 0; i < sz; i++) {
				data_front[i + 1] = merge(data_front[i], v[now][i]);
				data_back[sz - i - 1] = merge(v[now][sz - i - 1], data_back[sz - i]);
			}
			for(int i = 0; i < sz; i++) {
				auto nxtans = merge(ans_par, merge(data_front[i], data_back[i + 1]));
				rerooting(tr.edges[now][i].to, nxtans, now, tr.edges[now][i].len);
			}
			ret[now] = merge(ans_par, data_front[sz]);
			return;
		};
		rerooting(root, unit, root, 0);

		return ret;
	}

	// HL分解
};

// 強連結成分分解
struct SCC {
	graph<int> ng, rg;	// normal graph, reversed graph
	vector<int> compo;	// compo[i] = 新グラフでiが属する頂点集合番号
	vector<int> order;
	vector<bool> used;
	graph<int> ret;
	// g:元のグラフ, ret:強連結成分分解後のグラフ

	template <class T>
	SCC(graph<T> &g) : ng(g.ver), rg(g.ver), compo(g.ver, -1), used(g.ver, false) {
		for(int from = 0; from < g.ver; from++) {
			for(auto &e : g.edges[from]) {
				ng.update(e.from, e.to, 1, 1);
				rg.update(e.to, e.from, 1, 1);
			}
		}

		for(int i = 0; i < ng.ver; i++) dfs(i);
		reverse(order.begin(), order.end());
		int group = 0;
		for(auto i : order)
			if(compo[i] == -1) rdfs(i, group), group++;
		ret.edges.resize(group);
		for(int i = 0; i < g.ver; i++) {
			for(auto &e : g.edges[i]) {
				int s = compo[i], t = compo[e.to];
				if(s != t) ret.update(s, t, 1, 1);
			}
		}
	}

	int operator[](int k) { return compo[k]; }

	void dfs(int now) {
		if(used[now]) return;
		used[now] = true;
		for(auto &e : ng.edges[now]) dfs(e.to);
		order.push_back(now);
	}

	void rdfs(int now, int count) {
		if(compo[now] != -1) return;
		compo[now] = count;
		for(auto &e : rg.edges[now]) rdfs(e.to, count);
	}
};

#pragma endregion

bool nim(vll s) {
	ll g = 0;
	foa(t, s) g ^= t;
	return bool(g);
}

bool fairgame(vll s, ll take) {
	ll g = 0;
	foa(t, s) g ^= t % (take + 1);
	return bool(g);
}

bool solve(int n) {
	ll a, b;
	cin >> a >> b;
	VEC(ll, s, n);
	sort(all(s));
	if(s.back() <= min(a, b)) return nim(s);
	if(a == b) return fairgame(s, a);
	if(a > b) return true;
	if(n > 1 && s[n - 2] > a) return false;
	ll g = 0;
	rep(i, n - 1) { g ^= s[i]; }
	ll musttake = s.back() - g;
	return 0 < musttake && musttake <= a;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n && n) {
		cout << (solve(n) ? "Hanako" : "Jiro") << dl;
	}
	return 0;
}
accuracy: 0.7252747252747253
time_ms: 10
memory_kb: 4660
final_rank: 11

code_snippet: /*	author:  Kite_kuma
	created: 2021.11.03 09:47:45 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

template <class T = long long>
struct edge {
	T len;
	int from;
	int to;
	bool operator<(const edge a) const {
		if(len != a.len) return len < a.len;
		if(from != a.from) return from < a.from;
		return to < a.to;
	}
	bool operator>(const edge a) const {
		if(len != a.len) return len > a.len;
		if(from != a.from) return from > a.from;
		return to > a.to;
	}
};
template <class T = long long>
struct graph {	// 0-indexed
	T const INF = numeric_limits<T>::max() / 3;
	vector<vector<edge<T>>> edges;
	int ver;

	// constructor
	graph() = default;
	graph(int vertex) : ver(vertex), edges(vertex) {}

	//辺の追加 (0-indexed)
	void update(int from, int to, T len = 1, bool direction = 1) {	// checked
		edge<T> e;
		e.len = len;
		e.from = from;
		e.to = to;
		edges[from].push_back(e);
		if(!direction) {
			swap(e.to, e.from);
			edges[to].push_back(e);
		}
	}

	//入力受取 (1-indexed)
	void input(int edge_num, bool direction = false, bool weight = false, int index = 1) {	// checked
		for(int i = 0; i < edge_num; i++) {
			int a;
			int b;
			cin >> a >> b;
			a -= index;
			b -= index;
			T c;
			if(weight)
				cin >> c;
			else
				c = 1;
			update(a, b, c, direction);
		}
	}

	// 辺の長さを全て1とみたときの単一始点最短経路 (無理なときはINF)
	vector<T> bfs(int start) {	// checked
		// https://atcoder.jp/contests/abc007/submissions/me
		vector<T> ret(ver, INF);
		queue<int> q;
		q.push(start);
		ret[start] = 0;
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(ret[e.to] != INF) continue;
				q.push(e.to);
				ret[e.to] = ret[now] + 1;
			}
		}
		return ret;
	}

	vector<T> zero_one_bfs(int start) {	 // checked
		vector<T> ret(ver, INF);
		deque<int> deq;
		deq.push_back(start);
		ret[start] = 0;
		while(!deq.empty()) {
			int now = deq.front();
			deq.pop_front();
			for(auto &e : edges[now]) {
				if(chmin(ret[e.to], ret[now] + e.len)) {
					if(e.len)
						deq.push_back(e.to);
					else
						deq.push_front(e.to);
				}
			}
		}
		return ret;
	}

	//長さが負のpathがないときの単一始点最短経路<vll> O((ver)log(ver)+(edge))
	vector<T> dijkstra(int start) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_A/judge/4817136/C++14
		vector<T> ret(ver, (T)INF);													  //{dist,place}
		priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> p;  //{dist,place}
		p.push({0, start});
		ret[start] = 0;

		while(!p.empty()) {
			T dist = p.top().first;
			int place = p.top().second;
			p.pop();
			if(ret[place] < dist) continue;
			for(auto &next : edges[place]) {
				int nextplace = next.to;
				T dis = next.len;
				if(ret[nextplace] > dist + dis) {
					ret[nextplace] = dist + dis;
					p.push({ret[nextplace], nextplace});
				}
			}
		}
		return ret;
	}

	//単一始点最短経路 O((ver)*(edge))
	//辿り着けないとき ret[i] = INF;
	//ある頂点までのコストが無限に小さくなり得るとき→ ret[i] = -INF;
	vector<T> BellmanFord(int start) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_B/judge/4817139/C++14
		vector<T> ret(ver, INF);
		ret[start] = 0;
		for(int loop = 0; loop < ver - 1; loop++) {
			for(int v = 0; v < ver; v++) {
				if(ret[v] == INF) continue;
				for(auto &e : edges[v]) {
					ret[e.to] = min(ret[e.to], ret[v] + e.len);
				}
			}
		}

		//無限降下点の検索
		queue<int> q;
		vector<bool> chk(ver, 0);
		for(int v = 0; v < ver; v++) {
			if(ret[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(ret[e.to] > ret[v] + e.len) {
					ret[e.to] = ret[v] + e.len;
					if(!chk[e.to]) {
						q.push(e.to);
						chk[e.to] = 1;
					}
				}
			}
		}
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					q.push(e.to);
				}
			}
		}
		for(int i = 0; i < ver; i++)
			if(chk[i]) ret[i] = -INF;

		return ret;
	}

	//閉路に含まれない頂点列挙
	//要素数がver未満なら閉路が存在、そうでなければ閉路は存在しない
	vector<int> topo_sort() {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_B/judge/4817106/C++14
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_A/judge/4817110/C++14
		vector<int> num_input(ver);
		// 入次数
		for(int i = 0; i < ver; i++) {
			for(auto e : edges[i]) {
				num_input[e.to]++;
			}
		}
		// 入次数が0のノードをqueueで管理する
		queue<int> que;
		for(int i = 0; i < ver; i++) {
			if(num_input[i] == 0) {
				que.push(i);
			}
		}
		vector<int> ans;
		while(!que.empty()) {
			auto node = que.front();
			que.pop();
			ans.push_back(node);
			// 頂点の削除
			for(auto e : edges[node]) {
				num_input[e.to]--;
				// 行き先の入次数が0になったらqueueに追加
				if(num_input[e.to] == 0) {
					que.push(e.to);
				}
			}
		}
		return ans;
	}

	//{{端点、端点},直径の大きさ}
	pair<pair<int, int>, T> DiameterOfTree(bool weigh = true) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_A/judge/4817099/C++14
		vector<T> vec;
		vec = weigh ? dijkstra(0) : bfs(0);
		int v1 = -1;
		T dia = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				dia = vec[i];
				v1 = i;
			}

		vec = weigh ? dijkstra(v1) : bfs(v1);
		dia = -1;
		int v2 = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				v2 = i;
				dia = vec[i];
			}

		pair<pair<int, int>, T> ans = {{v1, v2}, dia};
		return ans;
	}

	//無向木構造を根から葉に伸びる有向木構造に書き換える
	graph<T> RootToLeaf(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(now, e.to, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//無向木構造を葉から根に伸びる有向木構造に書き換える
	graph<T> LeafToRoot(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(e.to, now, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		ret.update(root, root, 0);
		return ret;
	}

	// LeafToRootのvector版.par[i]=iの親の頂点
	vector<int> par(int root) {	 // 0-indexed
		vector<int> ret(ver, -1);
		ret[root] = root;  // rootの親はroot
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to] != -1) continue;
				ret[e.to] = now;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	vector<edge<T>> ParentAndDistance(int root) {  // 0-indexed
		vector<edge<T>> ret(ver);
		for(int i = 0; i < ver; i++) ret[i].to = -1;
		ret[root].to = root;  // rootの親はroot
		ret[root].len = 0;	  // rootの親との距離は0
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to].to != -1) continue;
				ret[e.to].to = now;
				ret[e.to].len = e.len;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//隣接sheet.主にwarshall用
	vector<vector<T>> GraphArray(void) {  // chkecked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_C/judge/4817090/C++14
		vector<vector<T>> ret(ver, vector<T>(ver, INF));
		for(int from = 0; from < ver; from++) {
			for(auto &e : edges[from]) {
				ret[from][e.to] = e.len;
			}
			ret[from][from] = 0;
		}
		return ret;
	}

	graph<T> Prim(bool direction = 0, int start = 0) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_2_A/judge/4817129/C++14
		graph<T> ret(ver);
		priority_queue<edge<T>, vector<edge<T>>, greater<edge<T>>> p;
		for(auto &e : edges[start]) {
			p.push(e);
		}
		vector<bool> chk(ver, 0);
		chk[start] = 1;
		while(!p.empty()) {
			auto ed = p.top();
			p.pop();
			if(chk[ed.to]) continue;
			chk[ed.to] = 1;
			ret.update(ed.from, ed.to, ed.len, direction);
			for(auto &e : edges[ed.to]) {
				p.push(e);
			}
		}
		return ret;
	}

	//各頂点を根としたときの木の高さ
	vector<T> height(int start = 0) {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_B/judge/4817082/C++14
		vector<T> fir(ver, -1), sec(ver, -1);
		function<T(int, int)> dfs = [&](int now, int par) {
			T f = 0, s = 0;	 // startを根としたときのnowからの深さ1番目、2番目
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				s = max(s, dfs(e.to, now) + e.len);
				if(f < s) swap(f, s);
			}
			sec[now] = s;
			return fir[now] = f;
		};
		dfs(start, -1);
		function<void(int, int, T, T, T)> sol = [&](int now, int par, T parf, T pars, T parlen) {
			if(fir[now] + parlen == parf) parf = pars;
			sec[now] = max(sec[now], parf + parlen);
			if(fir[now] < sec[now]) swap(fir[now], sec[now]);
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				sol(e.to, now, fir[now], sec[now], e.len);
			}
			return;
		};
		sol(start, -1, -1, -1, -1);
		return fir;
	}

	//全方位木DP
	//マージ関数、上に送るための関数、単位元、はじめの根
	// 関数はstd::functionで渡す
	template <class U>
	vector<U> ReRootingDP(U &unit, function<U(U, U)> &merge, function<U(int, U, T)> &send, int root = 0) {
		auto tr = RootToLeaf(root);
		vector<vector<U>> v(ver);
		vector<U> ret(ver);	 //求める答

		function<U(int)> treeDP = [&](int now) {
			U res = unit;
			vector<U> vec;
			for(auto &e : tr.edges[now]) {
				U u = send(e.to, treeDP(e.to), e.len);
				v[now].push_back(u);
				res = merge(res, u);
			}
			return res;
		};
		treeDP(root);

		function<void(int, U, int, T)> rerooting = [&](int now, U ans_par, int par, T len) {
			if(now != root) ans_par = send(par, ans_par, len);
			int sz = v[now].size();
			vector<U> data_front(sz + 1), data_back(sz + 1);
			data_front[0] = data_back[sz] = unit;
			for(int i = 0; i < sz; i++) {
				data_front[i + 1] = merge(data_front[i], v[now][i]);
				data_back[sz - i - 1] = merge(v[now][sz - i - 1], data_back[sz - i]);
			}
			for(int i = 0; i < sz; i++) {
				auto nxtans = merge(ans_par, merge(data_front[i], data_back[i + 1]));
				rerooting(tr.edges[now][i].to, nxtans, now, tr.edges[now][i].len);
			}
			ret[now] = merge(ans_par, data_front[sz]);
			return;
		};
		rerooting(root, unit, root, 0);

		return ret;
	}

	// HL分解
};

// 強連結成分分解
struct SCC {
	graph<int> ng, rg;	// normal graph, reversed graph
	vector<int> compo;	// compo[i] = 新グラフでiが属する頂点集合番号
	vector<int> order;
	vector<bool> used;
	graph<int> ret;
	// g:元のグラフ, ret:強連結成分分解後のグラフ

	template <class T>
	SCC(graph<T> &g) : ng(g.ver), rg(g.ver), compo(g.ver, -1), used(g.ver, false) {
		for(int from = 0; from < g.ver; from++) {
			for(auto &e : g.edges[from]) {
				ng.update(e.from, e.to, 1, 1);
				rg.update(e.to, e.from, 1, 1);
			}
		}

		for(int i = 0; i < ng.ver; i++) dfs(i);
		reverse(order.begin(), order.end());
		int group = 0;
		for(auto i : order)
			if(compo[i] == -1) rdfs(i, group), group++;
		ret.edges.resize(group);
		for(int i = 0; i < g.ver; i++) {
			for(auto &e : g.edges[i]) {
				int s = compo[i], t = compo[e.to];
				if(s != t) ret.update(s, t, 1, 1);
			}
		}
	}

	int operator[](int k) { return compo[k]; }

	void dfs(int now) {
		if(used[now]) return;
		used[now] = true;
		for(auto &e : ng.edges[now]) dfs(e.to);
		order.push_back(now);
	}

	void rdfs(int now, int count) {
		if(compo[now] != -1) return;
		compo[now] = count;
		for(auto &e : rg.edges[now]) rdfs(e.to, count);
	}
};

#pragma endregion

bool nim(vll s) {
	ll g = 0;
	foa(t, s) g ^= t;
	return bool(g);
}

bool fairgame(vll s, ll take) {
	ll g = 0;
	foa(t, s) g ^= t % (take + 1);
	return bool(g);
}

bool solve(int n) {
	ll a, b;
	cin >> a >> b;
	VEC(ll, s, n);

	sort(all(s));
	if(s.back() <= min(a, b)) return nim(s);

	if(a == b) return fairgame(s, a);
	if(a > b) return true;

	// a < b

	// if(count_if(all(s), [&a](ll val) { return val > a; }) > 1) return false;
	if(n > 1 && s[n - 2] > a) return false;

	ll g = 0;
	rep(i, n - 1) { g ^= s[i]; }

	ll musttake = s.back() - g;
	return 0 < musttake && musttake <= a;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n && n) {
		cout << (solve(n) ? "Hanako" : "Jiro") << dl;
	}
	return 0;
}
accuracy: 0.7252747252747253
time_ms: 10
memory_kb: 4652
final_rank: 10

code_snippet: /*	author:  Kite_kuma
	created: 2021.11.03 09:47:45 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

template <class T = long long>
struct edge {
	T len;
	int from;
	int to;
	bool operator<(const edge a) const {
		if(len != a.len) return len < a.len;
		if(from != a.from) return from < a.from;
		return to < a.to;
	}
	bool operator>(const edge a) const {
		if(len != a.len) return len > a.len;
		if(from != a.from) return from > a.from;
		return to > a.to;
	}
};
template <class T = long long>
struct graph {	// 0-indexed
	T const INF = numeric_limits<T>::max() / 3;
	vector<vector<edge<T>>> edges;
	int ver;

	// constructor
	graph() = default;
	graph(int vertex) : ver(vertex), edges(vertex) {}

	//辺の追加 (0-indexed)
	void update(int from, int to, T len = 1, bool direction = 1) {	// checked
		edge<T> e;
		e.len = len;
		e.from = from;
		e.to = to;
		edges[from].push_back(e);
		if(!direction) {
			swap(e.to, e.from);
			edges[to].push_back(e);
		}
	}

	//入力受取 (1-indexed)
	void input(int edge_num, bool direction = false, bool weight = false, int index = 1) {	// checked
		for(int i = 0; i < edge_num; i++) {
			int a;
			int b;
			cin >> a >> b;
			a -= index;
			b -= index;
			T c;
			if(weight)
				cin >> c;
			else
				c = 1;
			update(a, b, c, direction);
		}
	}

	// 辺の長さを全て1とみたときの単一始点最短経路 (無理なときはINF)
	vector<T> bfs(int start) {	// checked
		// https://atcoder.jp/contests/abc007/submissions/me
		vector<T> ret(ver, INF);
		queue<int> q;
		q.push(start);
		ret[start] = 0;
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(ret[e.to] != INF) continue;
				q.push(e.to);
				ret[e.to] = ret[now] + 1;
			}
		}
		return ret;
	}

	vector<T> zero_one_bfs(int start) {	 // checked
		vector<T> ret(ver, INF);
		deque<int> deq;
		deq.push_back(start);
		ret[start] = 0;
		while(!deq.empty()) {
			int now = deq.front();
			deq.pop_front();
			for(auto &e : edges[now]) {
				if(chmin(ret[e.to], ret[now] + e.len)) {
					if(e.len)
						deq.push_back(e.to);
					else
						deq.push_front(e.to);
				}
			}
		}
		return ret;
	}

	//長さが負のpathがないときの単一始点最短経路<vll> O((ver)log(ver)+(edge))
	vector<T> dijkstra(int start) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_A/judge/4817136/C++14
		vector<T> ret(ver, (T)INF);													  //{dist,place}
		priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> p;  //{dist,place}
		p.push({0, start});
		ret[start] = 0;

		while(!p.empty()) {
			T dist = p.top().first;
			int place = p.top().second;
			p.pop();
			if(ret[place] < dist) continue;
			for(auto &next : edges[place]) {
				int nextplace = next.to;
				T dis = next.len;
				if(ret[nextplace] > dist + dis) {
					ret[nextplace] = dist + dis;
					p.push({ret[nextplace], nextplace});
				}
			}
		}
		return ret;
	}

	//単一始点最短経路 O((ver)*(edge))
	//辿り着けないとき ret[i] = INF;
	//ある頂点までのコストが無限に小さくなり得るとき→ ret[i] = -INF;
	vector<T> BellmanFord(int start) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_B/judge/4817139/C++14
		vector<T> ret(ver, INF);
		ret[start] = 0;
		for(int loop = 0; loop < ver - 1; loop++) {
			for(int v = 0; v < ver; v++) {
				if(ret[v] == INF) continue;
				for(auto &e : edges[v]) {
					ret[e.to] = min(ret[e.to], ret[v] + e.len);
				}
			}
		}

		//無限降下点の検索
		queue<int> q;
		vector<bool> chk(ver, 0);
		for(int v = 0; v < ver; v++) {
			if(ret[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(ret[e.to] > ret[v] + e.len) {
					ret[e.to] = ret[v] + e.len;
					if(!chk[e.to]) {
						q.push(e.to);
						chk[e.to] = 1;
					}
				}
			}
		}
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					q.push(e.to);
				}
			}
		}
		for(int i = 0; i < ver; i++)
			if(chk[i]) ret[i] = -INF;

		return ret;
	}

	//閉路に含まれない頂点列挙
	//要素数がver未満なら閉路が存在、そうでなければ閉路は存在しない
	vector<int> topo_sort() {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_B/judge/4817106/C++14
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_A/judge/4817110/C++14
		vector<int> num_input(ver);
		// 入次数
		for(int i = 0; i < ver; i++) {
			for(auto e : edges[i]) {
				num_input[e.to]++;
			}
		}
		// 入次数が0のノードをqueueで管理する
		queue<int> que;
		for(int i = 0; i < ver; i++) {
			if(num_input[i] == 0) {
				que.push(i);
			}
		}
		vector<int> ans;
		while(!que.empty()) {
			auto node = que.front();
			que.pop();
			ans.push_back(node);
			// 頂点の削除
			for(auto e : edges[node]) {
				num_input[e.to]--;
				// 行き先の入次数が0になったらqueueに追加
				if(num_input[e.to] == 0) {
					que.push(e.to);
				}
			}
		}
		return ans;
	}

	//{{端点、端点},直径の大きさ}
	pair<pair<int, int>, T> DiameterOfTree(bool weigh = true) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_A/judge/4817099/C++14
		vector<T> vec;
		vec = weigh ? dijkstra(0) : bfs(0);
		int v1 = -1;
		T dia = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				dia = vec[i];
				v1 = i;
			}

		vec = weigh ? dijkstra(v1) : bfs(v1);
		dia = -1;
		int v2 = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				v2 = i;
				dia = vec[i];
			}

		pair<pair<int, int>, T> ans = {{v1, v2}, dia};
		return ans;
	}

	//無向木構造を根から葉に伸びる有向木構造に書き換える
	graph<T> RootToLeaf(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(now, e.to, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//無向木構造を葉から根に伸びる有向木構造に書き換える
	graph<T> LeafToRoot(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(e.to, now, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		ret.update(root, root, 0);
		return ret;
	}

	// LeafToRootのvector版.par[i]=iの親の頂点
	vector<int> par(int root) {	 // 0-indexed
		vector<int> ret(ver, -1);
		ret[root] = root;  // rootの親はroot
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to] != -1) continue;
				ret[e.to] = now;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	vector<edge<T>> ParentAndDistance(int root) {  // 0-indexed
		vector<edge<T>> ret(ver);
		for(int i = 0; i < ver; i++) ret[i].to = -1;
		ret[root].to = root;  // rootの親はroot
		ret[root].len = 0;	  // rootの親との距離は0
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to].to != -1) continue;
				ret[e.to].to = now;
				ret[e.to].len = e.len;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//隣接sheet.主にwarshall用
	vector<vector<T>> GraphArray(void) {  // chkecked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_C/judge/4817090/C++14
		vector<vector<T>> ret(ver, vector<T>(ver, INF));
		for(int from = 0; from < ver; from++) {
			for(auto &e : edges[from]) {
				ret[from][e.to] = e.len;
			}
			ret[from][from] = 0;
		}
		return ret;
	}

	graph<T> Prim(bool direction = 0, int start = 0) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_2_A/judge/4817129/C++14
		graph<T> ret(ver);
		priority_queue<edge<T>, vector<edge<T>>, greater<edge<T>>> p;
		for(auto &e : edges[start]) {
			p.push(e);
		}
		vector<bool> chk(ver, 0);
		chk[start] = 1;
		while(!p.empty()) {
			auto ed = p.top();
			p.pop();
			if(chk[ed.to]) continue;
			chk[ed.to] = 1;
			ret.update(ed.from, ed.to, ed.len, direction);
			for(auto &e : edges[ed.to]) {
				p.push(e);
			}
		}
		return ret;
	}

	//各頂点を根としたときの木の高さ
	vector<T> height(int start = 0) {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_B/judge/4817082/C++14
		vector<T> fir(ver, -1), sec(ver, -1);
		function<T(int, int)> dfs = [&](int now, int par) {
			T f = 0, s = 0;	 // startを根としたときのnowからの深さ1番目、2番目
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				s = max(s, dfs(e.to, now) + e.len);
				if(f < s) swap(f, s);
			}
			sec[now] = s;
			return fir[now] = f;
		};
		dfs(start, -1);
		function<void(int, int, T, T, T)> sol = [&](int now, int par, T parf, T pars, T parlen) {
			if(fir[now] + parlen == parf) parf = pars;
			sec[now] = max(sec[now], parf + parlen);
			if(fir[now] < sec[now]) swap(fir[now], sec[now]);
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				sol(e.to, now, fir[now], sec[now], e.len);
			}
			return;
		};
		sol(start, -1, -1, -1, -1);
		return fir;
	}

	//全方位木DP
	//マージ関数、上に送るための関数、単位元、はじめの根
	// 関数はstd::functionで渡す
	template <class U>
	vector<U> ReRootingDP(U &unit, function<U(U, U)> &merge, function<U(int, U, T)> &send, int root = 0) {
		auto tr = RootToLeaf(root);
		vector<vector<U>> v(ver);
		vector<U> ret(ver);	 //求める答

		function<U(int)> treeDP = [&](int now) {
			U res = unit;
			vector<U> vec;
			for(auto &e : tr.edges[now]) {
				U u = send(e.to, treeDP(e.to), e.len);
				v[now].push_back(u);
				res = merge(res, u);
			}
			return res;
		};
		treeDP(root);

		function<void(int, U, int, T)> rerooting = [&](int now, U ans_par, int par, T len) {
			if(now != root) ans_par = send(par, ans_par, len);
			int sz = v[now].size();
			vector<U> data_front(sz + 1), data_back(sz + 1);
			data_front[0] = data_back[sz] = unit;
			for(int i = 0; i < sz; i++) {
				data_front[i + 1] = merge(data_front[i], v[now][i]);
				data_back[sz - i - 1] = merge(v[now][sz - i - 1], data_back[sz - i]);
			}
			for(int i = 0; i < sz; i++) {
				auto nxtans = merge(ans_par, merge(data_front[i], data_back[i + 1]));
				rerooting(tr.edges[now][i].to, nxtans, now, tr.edges[now][i].len);
			}
			ret[now] = merge(ans_par, data_front[sz]);
			return;
		};
		rerooting(root, unit, root, 0);

		return ret;
	}

	// HL分解
};

// 強連結成分分解
struct SCC {
	graph<int> ng, rg;	// normal graph, reversed graph
	vector<int> compo;	// compo[i] = 新グラフでiが属する頂点集合番号
	vector<int> order;
	vector<bool> used;
	graph<int> ret;
	// g:元のグラフ, ret:強連結成分分解後のグラフ

	template <class T>
	SCC(graph<T> &g) : ng(g.ver), rg(g.ver), compo(g.ver, -1), used(g.ver, false) {
		for(int from = 0; from < g.ver; from++) {
			for(auto &e : g.edges[from]) {
				ng.update(e.from, e.to, 1, 1);
				rg.update(e.to, e.from, 1, 1);
			}
		}

		for(int i = 0; i < ng.ver; i++) dfs(i);
		reverse(order.begin(), order.end());
		int group = 0;
		for(auto i : order)
			if(compo[i] == -1) rdfs(i, group), group++;
		ret.edges.resize(group);
		for(int i = 0; i < g.ver; i++) {
			for(auto &e : g.edges[i]) {
				int s = compo[i], t = compo[e.to];
				if(s != t) ret.update(s, t, 1, 1);
			}
		}
	}

	int operator[](int k) { return compo[k]; }

	void dfs(int now) {
		if(used[now]) return;
		used[now] = true;
		for(auto &e : ng.edges[now]) dfs(e.to);
		order.push_back(now);
	}

	void rdfs(int now, int count) {
		if(compo[now] != -1) return;
		compo[now] = count;
		for(auto &e : rg.edges[now]) rdfs(e.to, count);
	}
};

#pragma endregion

bool nim(vll s) {
	ll g = 0;
	foa(t, s) g ^= t;
	return bool(g);
}

bool fairgame(vll s, ll take) {
	ll g = 0;
	foa(t, s) g ^= t % (take + 1);
	return bool(g);
}

bool solve(int n) {
	ll a, b;
	cin >> a >> b;
	VEC(ll, s, n);

	sort(all(s));
	if(s.back() <= min(a, b)) return nim(s);

	if(a == b) return fairgame(s, a);
	if(a > b) return true;

	// a < b

	// if(count_if(all(s), [&a](ll val) { return val > a; }) > 1) return false;
	if(n > 1 && s[n - 2] > a) return false;

	ll g = 0;
	rep(i, n - 1) { g ^= s[i]; }

	ll musttake = s.back() - g;
	return 0 <= musttake <= a;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n && n) {
		cout << (solve(n) ? "Hanako" : "Jiro") << dl;
	}
	return 0;
}
accuracy: 0.6483516483516484
time_ms: 10
memory_kb: 4652
final_rank: 15

code_snippet: /*	author:  Kite_kuma
	created: 2021.11.03 09:47:45 */

// #ifdef LOCAL
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;

#pragma region macros

#define foa(s, v) for(auto &s : v)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define popcnt(n) __builtin_popcountll((long long)n)

#define REPname(a, b, c, d, e, ...) e
#define rep(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int Counter_in_rep_macro = 0; Counter_in_rep_macro < (x); ++Counter_in_rep_macro)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))

#define DREPname(a, b, c, d, e, ...) e
#define drep(...) DREPname(__VA_ARGS__, DREP3, DREP2, DREP1)(__VA_ARGS__)
#define DREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define DREP2(i, l, r) for(int i = (r)-1; i >= (l); --i)
#define DREP3(i, l, r, c) for(int i = (r)-1; i >= (l); i -= (c))

#pragma endregion

#pragma region aliases

using ll = long long;
using ld = long double;
using ull = unsigned long long;
using vi = std::vector<int>;
using vvi = std::vector<std::vector<int>>;
using vvvi = std::vector<std::vector<std::vector<int>>>;
using vll = std::vector<ll>;
using vvll = std::vector<vll>;
using vvvll = std::vector<vvll>;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;
template <class T = ll>
using V = std::vector<T>;
template <class T = ll>
using VV = V<V<T>>;
template <class T = ll>
using VVV = V<V<V<T>>>;
template <class T = ll>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
template <class T = ll>
using pqdn = std::priority_queue<T>;

#pragma endregion

#pragma region constants

const int inf = 1e9;
const long long INF = 1e18;
const long double pi = acos(-1);
const char dl = '\n';
const char sp = ' ';
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};

const int mod_1000000007 = 1000000007;
const int mod_998244353 = 998244353;

#pragma endregion

#pragma region basic_operation

template <class T0, class T1, class T2>
inline bool in_range(T0 x, T1 lef, T2 rig) {
	return ((lef <= x) && (x < rig));
}

template <class T>
inline bool chmin(T &a, T b) {
	if(a > b) {
		a = b;
		return true;
	}
	return false;
}
template <class T>
inline bool chmax(T &a, T b) {
	if(a < b) {
		a = b;
		return true;
	}
	return false;
}

void Yes(bool f = 1) { std::cout << (f ? "Yes" : "No") << '\n'; }
void No() { std::cout << "No\n"; }
void YES(bool f = 1) { std::cout << (f ? "YES" : "NO") << '\n'; }
void NO() { std::cout << "NO\n"; }

template <class T>
void drop(T answer) {
	std::cout << answer << '\n';
	exit(0);
}

void err(bool flag = true) {
	if(!flag) return;
	std::cout << -1 << '\n';
	exit(0);
}

template <class T>
void vout(std::vector<T> const &v, bool vertically = 0) {
	if(vertically) {
		for(auto const &a : v) {
			std::cout << a << '\n';
		}
		return;
	}
	for(auto it = v.begin(); it != v.end(); it++) {
		std::cout << (*it);
		if(it != v.end() - 1) {
			std::cout << ' ';
		}
	}
	std::cout << '\n';
	return;
}

inline void print() { std::cout << '\n'; }
template <class T>
inline void print(T x) {
	std::cout << x << '\n';
	return;
}
template <typename Head, typename... Tail>
void print(Head H, Tail... T) {
	std::cout << H << " ";
	print(T...);
}

template <class T>
void add(std::vector<T> &v, T val) {
	for(auto &a : v) a += val;
	return;
}

template <class T>
T dup(T a, T b) {
	assert(b != 0);
	return (a + b - 1) / b;
}

template <class T>
T greatest_lower_multiple(T x, T d) {
	if(d == 0) return 0;
	if(d < 0) d *= -1;
	T y = x % d;
	if(y < 0) y += d;
	return x - y;
}

template <class T>
T least_upper_multiple(T x, T d) {
	return -greatest_lower_multiple(-x, d);
}

long long POW(long long a, long long n) {
	long long res = 1;
	while(n > 0) {
		if(n & 1) res = res * a;
		a = a * a;
		n >>= 1;
	}
	return res;
}

long long modpow(long long a, long long n, long long mod) {	 // a^n mod
	assert(n >= 0 && mod);
	if(mod == 1) return 0LL;
	long long res = 1;
	a %= mod;
	while(n > 0) {
		if(n & 1) res = res * a % mod;
		a = a * a % mod;
		n >>= 1;
	}
	return res < 0 ? res + mod : res;
}

// return x which satisfies a * x % mod == gcd(a, mod)
// not (mod | a)
long long modinv(long long a, long long mod) {
	long long b = mod, u = 1, v = 0;
	while(b) {
		long long t = a / b;
		a -= t * b;
		std::swap(a, b);
		u -= t * v;
		std::swap(u, v);
	}
	u %= mod;
	if(u < 0) u += mod;
	return u;
}

template <class T>
int lb(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::lower_bound(a.begin(), a.end(), x));
}
template <class T>
int ub(const std::vector<T> &a, const T x) {
	return std::distance(a.begin(), std::upper_bound(a.begin(), a.end(), x));
}
template <class T>
void unq_sort(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<int> press(std::vector<T> &a) {
	auto vec = a;
	unq_sort(vec);
	std::vector<int> ret;
	for(auto &v : a) ret.push_back(lb(vec, v));
	return ret;
}

#pragma endregion

#pragma region input
#define VEC(type, name, size) \
	vector<type> name(size);  \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                     \
	vector<vector<type>> name(h, vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)        \
	string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHR(...)      \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DBL(...)        \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define TPL3(type0, type1, type2, name)   \
	std::tuple<type0, type1, type2> name; \
	scanner::INPUT(name);
#define TPL4(type0, type1, type2, type3, name)   \
	std::tuple<type0, type1, type2, type3> name; \
	scanner::INPUT(name);

namespace scanner {
template <class T>
void scan(T &a) {
	std::cin >> a;
}

template <class T, class L>
void scan(std::pair<T, L> &p) {
	scan(p.first);
	scan(p.second);
}

template <class T0, class T1, class T2>
void scan(std::tuple<T0, T1, T2> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	scan(t0);
	scan(t1);
	scan(t2);
	p = std::make_tuple(t0, t1, t2);
}

template <class T0, class T1, class T2, class T3>
void scan(std::tuple<T0, T1, T2, T3> &p) {
	T0 t0;
	T1 t1;
	T2 t2;
	T3 t3;
	scan(t0);
	scan(t1);
	scan(t2);
	scan(t3);
	p = std::make_tuple(t0, t1, t2, t3);
}

template <class T>
void scan(std::vector<T> &a) {
	for(auto &i : a) scan(i);
}

void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &... tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner

template <typename T1, typename T2>
std::istream &operator>>(std::istream &is, std::pair<T1, T2> &p) {
	is >> p.first >> p.second;
	return is;
}
#pragma endregion

#pragma region debug

#pragma region output
template <typename T1, typename T2>
std::ostream &std::operator<<(std::ostream &os, const std::pair<T1, T2> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &std::operator<<(std::ostream &os, const std::vector<T> &v) {
	for(int i = 0; i < (int)v.size(); i++) {
		if(i) os << " ";
		os << v[i];
	}
	return os;
}
#pragma endregion

#pragma region view

namespace viewer {
void view(const long long e) {
	if(e == INF)
		std::cerr << "INF";
	else if(e == -INF)
		std::cerr << "-INF";
	else
		std::cerr << e;
}

void view(const int e) {
	if(e == inf)
		std::cerr << "inf";
	else if(e == -inf)
		std::cerr << "-inf";
	else
		std::cerr << e;
}

template <typename T>
void view(const T e) {
	std::cerr << e;
}

template <typename T, typename U>
void view(const std::pair<T, U> &p) {
	std::cerr << "(";
	view(p.first);
	std::cerr << ", ";
	view(p.second);
	std::cerr << ")";
}

template <class T0, class T1, class T2>
void view(const std::tuple<T0, T1, T2> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ")";
}

template <class T0, class T1, class T2, class T3>
void view(const std::tuple<T0, T1, T2, T3> &p) {
	std::cerr << "(";
	view(std::get<0>(p));
	std::cerr << ", ";
	view(std::get<1>(p));
	std::cerr << ", ";
	view(std::get<2>(p));
	std::cerr << ", ";
	view(std::get<3>(p));
	std::cerr << ")";
}

template <typename T>
void view(const std::set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::unordered_set<T> &s) {
	if(s.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(auto &t : s) {
		view(t);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<T> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << "{ ";
	for(const auto &e : v) {
		view(e);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <typename T>
void view(const std::vector<std::vector<T>> &vv) {
	std::cerr << "{\n";
	for(const auto &v : vv) {
		std::cerr << "\t";
		view(v);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::vector<std::pair<T, U>> &v) {
	std::cerr << "{\n";
	for(const auto &c : v) {
		std::cerr << "\t(";
		view(c.first);
		std::cerr << ", ";
		view(c.second);
		std::cerr << ")\n";
	}
	std::cerr << "}";
}

template <class T0, class T1, class T2>
void view(const std::vector<std::tuple<T0, T1, T2>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <class T0, class T1, class T2, class T3>
void view(const std::vector<std::tuple<T0, T1, T2, T3>> &v) {
	if(v.empty()) {
		std::cerr << "{ }";
		return;
	}
	std::cerr << '{';
	for(const auto &t : v) {
		std::cerr << "\n\t";
		view(t);
		std::cerr << ",";
	}
	std::cerr << "\n}";
}

template <typename T, typename U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}

template <typename T, typename U>
void view(const std::unordered_map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &t : m) {
		std::cerr << "\t[";
		view(t.first);
		std::cerr << "] : ";
		view(t.second);
		std::cerr << '\n';
	}
	std::cerr << "}";
}
}  // namespace viewer

#pragma endregion

// when debugging : g++ foo.cpp -DLOCAL
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	viewer::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(0)
#define dump(x)                                      \
	do {                                             \
		std::cerr << __LINE__ << " " << #x << " : "; \
		viewer::view(x);                             \
		std::cerr << '\n';                           \
	} while(0)

#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif

#pragma endregion

#pragma region graph

template <class T = long long>
struct edge {
	T len;
	int from;
	int to;
	bool operator<(const edge a) const {
		if(len != a.len) return len < a.len;
		if(from != a.from) return from < a.from;
		return to < a.to;
	}
	bool operator>(const edge a) const {
		if(len != a.len) return len > a.len;
		if(from != a.from) return from > a.from;
		return to > a.to;
	}
};
template <class T = long long>
struct graph {	// 0-indexed
	T const INF = numeric_limits<T>::max() / 3;
	vector<vector<edge<T>>> edges;
	int ver;

	// constructor
	graph() = default;
	graph(int vertex) : ver(vertex), edges(vertex) {}

	//辺の追加 (0-indexed)
	void update(int from, int to, T len = 1, bool direction = 1) {	// checked
		edge<T> e;
		e.len = len;
		e.from = from;
		e.to = to;
		edges[from].push_back(e);
		if(!direction) {
			swap(e.to, e.from);
			edges[to].push_back(e);
		}
	}

	//入力受取 (1-indexed)
	void input(int edge_num, bool direction = false, bool weight = false, int index = 1) {	// checked
		for(int i = 0; i < edge_num; i++) {
			int a;
			int b;
			cin >> a >> b;
			a -= index;
			b -= index;
			T c;
			if(weight)
				cin >> c;
			else
				c = 1;
			update(a, b, c, direction);
		}
	}

	// 辺の長さを全て1とみたときの単一始点最短経路 (無理なときはINF)
	vector<T> bfs(int start) {	// checked
		// https://atcoder.jp/contests/abc007/submissions/me
		vector<T> ret(ver, INF);
		queue<int> q;
		q.push(start);
		ret[start] = 0;
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(ret[e.to] != INF) continue;
				q.push(e.to);
				ret[e.to] = ret[now] + 1;
			}
		}
		return ret;
	}

	vector<T> zero_one_bfs(int start) {	 // checked
		vector<T> ret(ver, INF);
		deque<int> deq;
		deq.push_back(start);
		ret[start] = 0;
		while(!deq.empty()) {
			int now = deq.front();
			deq.pop_front();
			for(auto &e : edges[now]) {
				if(chmin(ret[e.to], ret[now] + e.len)) {
					if(e.len)
						deq.push_back(e.to);
					else
						deq.push_front(e.to);
				}
			}
		}
		return ret;
	}

	//長さが負のpathがないときの単一始点最短経路<vll> O((ver)log(ver)+(edge))
	vector<T> dijkstra(int start) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_A/judge/4817136/C++14
		vector<T> ret(ver, (T)INF);													  //{dist,place}
		priority_queue<pair<T, int>, vector<pair<T, int>>, greater<pair<T, int>>> p;  //{dist,place}
		p.push({0, start});
		ret[start] = 0;

		while(!p.empty()) {
			T dist = p.top().first;
			int place = p.top().second;
			p.pop();
			if(ret[place] < dist) continue;
			for(auto &next : edges[place]) {
				int nextplace = next.to;
				T dis = next.len;
				if(ret[nextplace] > dist + dis) {
					ret[nextplace] = dist + dis;
					p.push({ret[nextplace], nextplace});
				}
			}
		}
		return ret;
	}

	//単一始点最短経路 O((ver)*(edge))
	//辿り着けないとき ret[i] = INF;
	//ある頂点までのコストが無限に小さくなり得るとき→ ret[i] = -INF;
	vector<T> BellmanFord(int start) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_B/judge/4817139/C++14
		vector<T> ret(ver, INF);
		ret[start] = 0;
		for(int loop = 0; loop < ver - 1; loop++) {
			for(int v = 0; v < ver; v++) {
				if(ret[v] == INF) continue;
				for(auto &e : edges[v]) {
					ret[e.to] = min(ret[e.to], ret[v] + e.len);
				}
			}
		}

		//無限降下点の検索
		queue<int> q;
		vector<bool> chk(ver, 0);
		for(int v = 0; v < ver; v++) {
			if(ret[v] == INF) continue;
			for(auto &e : edges[v]) {
				if(ret[e.to] > ret[v] + e.len) {
					ret[e.to] = ret[v] + e.len;
					if(!chk[e.to]) {
						q.push(e.to);
						chk[e.to] = 1;
					}
				}
			}
		}
		while(!q.empty()) {
			int now = q.front();
			q.pop();
			for(auto &e : edges[now]) {
				if(!chk[e.to]) {
					chk[e.to] = 1;
					q.push(e.to);
				}
			}
		}
		for(int i = 0; i < ver; i++)
			if(chk[i]) ret[i] = -INF;

		return ret;
	}

	//閉路に含まれない頂点列挙
	//要素数がver未満なら閉路が存在、そうでなければ閉路は存在しない
	vector<int> topo_sort() {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_B/judge/4817106/C++14
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_4_A/judge/4817110/C++14
		vector<int> num_input(ver);
		// 入次数
		for(int i = 0; i < ver; i++) {
			for(auto e : edges[i]) {
				num_input[e.to]++;
			}
		}
		// 入次数が0のノードをqueueで管理する
		queue<int> que;
		for(int i = 0; i < ver; i++) {
			if(num_input[i] == 0) {
				que.push(i);
			}
		}
		vector<int> ans;
		while(!que.empty()) {
			auto node = que.front();
			que.pop();
			ans.push_back(node);
			// 頂点の削除
			for(auto e : edges[node]) {
				num_input[e.to]--;
				// 行き先の入次数が0になったらqueueに追加
				if(num_input[e.to] == 0) {
					que.push(e.to);
				}
			}
		}
		return ans;
	}

	//{{端点、端点},直径の大きさ}
	pair<pair<int, int>, T> DiameterOfTree(bool weigh = true) {	 // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_A/judge/4817099/C++14
		vector<T> vec;
		vec = weigh ? dijkstra(0) : bfs(0);
		int v1 = -1;
		T dia = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				dia = vec[i];
				v1 = i;
			}

		vec = weigh ? dijkstra(v1) : bfs(v1);
		dia = -1;
		int v2 = -1;
		for(int i = 0; i < ver; i++)
			if((dia < vec[i])) {
				v2 = i;
				dia = vec[i];
			}

		pair<pair<int, int>, T> ans = {{v1, v2}, dia};
		return ans;
	}

	//無向木構造を根から葉に伸びる有向木構造に書き換える
	graph<T> RootToLeaf(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(now, e.to, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//無向木構造を葉から根に伸びる有向木構造に書き換える
	graph<T> LeafToRoot(int root) {	 // 0-indexed
		graph<T> ret(ver);
		vector<bool> chk(ver, 0);
		chk[root] = 1;
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(chk[e.to] == 1) continue;
				chk[e.to] = 1;
				ret.update(e.to, now, e.len);
				dfs(e.to);
			}
		};
		dfs(root);
		ret.update(root, root, 0);
		return ret;
	}

	// LeafToRootのvector版.par[i]=iの親の頂点
	vector<int> par(int root) {	 // 0-indexed
		vector<int> ret(ver, -1);
		ret[root] = root;  // rootの親はroot
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to] != -1) continue;
				ret[e.to] = now;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	vector<edge<T>> ParentAndDistance(int root) {  // 0-indexed
		vector<edge<T>> ret(ver);
		for(int i = 0; i < ver; i++) ret[i].to = -1;
		ret[root].to = root;  // rootの親はroot
		ret[root].len = 0;	  // rootの親との距離は0
		function<void(int)> dfs = [&](int now) {
			for(auto &e : edges[now]) {
				if(ret[e.to].to != -1) continue;
				ret[e.to].to = now;
				ret[e.to].len = e.len;
				dfs(e.to);
			}
		};
		dfs(root);
		return ret;
	}

	//隣接sheet.主にwarshall用
	vector<vector<T>> GraphArray(void) {  // chkecked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_1_C/judge/4817090/C++14
		vector<vector<T>> ret(ver, vector<T>(ver, INF));
		for(int from = 0; from < ver; from++) {
			for(auto &e : edges[from]) {
				ret[from][e.to] = e.len;
			}
			ret[from][from] = 0;
		}
		return ret;
	}

	graph<T> Prim(bool direction = 0, int start = 0) {	// checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_2_A/judge/4817129/C++14
		graph<T> ret(ver);
		priority_queue<edge<T>, vector<edge<T>>, greater<edge<T>>> p;
		for(auto &e : edges[start]) {
			p.push(e);
		}
		vector<bool> chk(ver, 0);
		chk[start] = 1;
		while(!p.empty()) {
			auto ed = p.top();
			p.pop();
			if(chk[ed.to]) continue;
			chk[ed.to] = 1;
			ret.update(ed.from, ed.to, ed.len, direction);
			for(auto &e : edges[ed.to]) {
				p.push(e);
			}
		}
		return ret;
	}

	//各頂点を根としたときの木の高さ
	vector<T> height(int start = 0) {  // checked
		// https://onlinejudge.u-aizu.ac.jp/status/users/Kite_kuma/submissions/1/GRL_5_B/judge/4817082/C++14
		vector<T> fir(ver, -1), sec(ver, -1);
		function<T(int, int)> dfs = [&](int now, int par) {
			T f = 0, s = 0;	 // startを根としたときのnowからの深さ1番目、2番目
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				s = max(s, dfs(e.to, now) + e.len);
				if(f < s) swap(f, s);
			}
			sec[now] = s;
			return fir[now] = f;
		};
		dfs(start, -1);
		function<void(int, int, T, T, T)> sol = [&](int now, int par, T parf, T pars, T parlen) {
			if(fir[now] + parlen == parf) parf = pars;
			sec[now] = max(sec[now], parf + parlen);
			if(fir[now] < sec[now]) swap(fir[now], sec[now]);
			for(auto &e : edges[now]) {
				if(e.to == par) continue;
				sol(e.to, now, fir[now], sec[now], e.len);
			}
			return;
		};
		sol(start, -1, -1, -1, -1);
		return fir;
	}

	//全方位木DP
	//マージ関数、上に送るための関数、単位元、はじめの根
	// 関数はstd::functionで渡す
	template <class U>
	vector<U> ReRootingDP(U &unit, function<U(U, U)> &merge, function<U(int, U, T)> &send, int root = 0) {
		auto tr = RootToLeaf(root);
		vector<vector<U>> v(ver);
		vector<U> ret(ver);	 //求める答

		function<U(int)> treeDP = [&](int now) {
			U res = unit;
			vector<U> vec;
			for(auto &e : tr.edges[now]) {
				U u = send(e.to, treeDP(e.to), e.len);
				v[now].push_back(u);
				res = merge(res, u);
			}
			return res;
		};
		treeDP(root);

		function<void(int, U, int, T)> rerooting = [&](int now, U ans_par, int par, T len) {
			if(now != root) ans_par = send(par, ans_par, len);
			int sz = v[now].size();
			vector<U> data_front(sz + 1), data_back(sz + 1);
			data_front[0] = data_back[sz] = unit;
			for(int i = 0; i < sz; i++) {
				data_front[i + 1] = merge(data_front[i], v[now][i]);
				data_back[sz - i - 1] = merge(v[now][sz - i - 1], data_back[sz - i]);
			}
			for(int i = 0; i < sz; i++) {
				auto nxtans = merge(ans_par, merge(data_front[i], data_back[i + 1]));
				rerooting(tr.edges[now][i].to, nxtans, now, tr.edges[now][i].len);
			}
			ret[now] = merge(ans_par, data_front[sz]);
			return;
		};
		rerooting(root, unit, root, 0);

		return ret;
	}

	// HL分解
};

// 強連結成分分解
struct SCC {
	graph<int> ng, rg;	// normal graph, reversed graph
	vector<int> compo;	// compo[i] = 新グラフでiが属する頂点集合番号
	vector<int> order;
	vector<bool> used;
	graph<int> ret;
	// g:元のグラフ, ret:強連結成分分解後のグラフ

	template <class T>
	SCC(graph<T> &g) : ng(g.ver), rg(g.ver), compo(g.ver, -1), used(g.ver, false) {
		for(int from = 0; from < g.ver; from++) {
			for(auto &e : g.edges[from]) {
				ng.update(e.from, e.to, 1, 1);
				rg.update(e.to, e.from, 1, 1);
			}
		}

		for(int i = 0; i < ng.ver; i++) dfs(i);
		reverse(order.begin(), order.end());
		int group = 0;
		for(auto i : order)
			if(compo[i] == -1) rdfs(i, group), group++;
		ret.edges.resize(group);
		for(int i = 0; i < g.ver; i++) {
			for(auto &e : g.edges[i]) {
				int s = compo[i], t = compo[e.to];
				if(s != t) ret.update(s, t, 1, 1);
			}
		}
	}

	int operator[](int k) { return compo[k]; }

	void dfs(int now) {
		if(used[now]) return;
		used[now] = true;
		for(auto &e : ng.edges[now]) dfs(e.to);
		order.push_back(now);
	}

	void rdfs(int now, int count) {
		if(compo[now] != -1) return;
		compo[now] = count;
		for(auto &e : rg.edges[now]) rdfs(e.to, count);
	}
};

#pragma endregion

bool nim(vll s) {
	ll g = 0;
	foa(t, s) g ^= t;
	return bool(g);
}

bool fairgame(vll s, ll take) {
	ll g = 0;
	foa(t, s) g ^= t % (take + 1);
	return bool(g);
}

bool solve(int n) {
	ll a, b;
	cin >> a >> b;
	VEC(ll, s, n);

	sort(all(s));
	if(s.back() <= min(a, b)) return nim(s);

	if(a == b) {
		return fairgame(s, a);
	}

	if(a > b) return true;

	// if(count_if(all(s), [&a](ll val) { return val > a; }) > 1) return false;
	if(n > 1 && s[n - 2] > a) return false;

	ll g = 0;
	rep(i, n - 1) { g ^= s[i]; }

	ll musttake = s.back() - g;
	return musttake <= a;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
	std::cout << std::fixed << std::setprecision(15);
	srand((unsigned)time(NULL));

	int n;
	while(cin >> n && n) {
		cout << (solve(n) ? "Hanako" : "Jiro") << dl;
	}
	return 0;
}
accuracy: 0.7252747252747253
time_ms: 10
memory_kb: 4660
final_rank: 11

code_snippet: #pragma GCC ta g("avx2")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define DEBUG
#ifdef DEBUG
template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << '(' << p.first << ',' << p.second << ')';
    return os;
}
template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
    os << '{';
    for(int i = 0; i < (int)v.size(); i++) {
        if(i) { os << ','; }
        os << v[i];
    }
    os << '}';
    return os;
}
void debugg() { cerr << endl; }
template <class T, class... Args>
void debugg(const T &x, const Args &... args) {
    cerr << " " << x;
    debugg(args...);
}
#define debug(...)                                                             \
    cerr << __LINE__ << " [" << #__VA_ARGS__ << "]: ", debugg(__VA_ARGS__)
#define dump(x) cerr << __LINE__ << " " << #x << " = " << (x) << endl
#else
#define debug(...) (void(0))
#define dump(x) (void(0))
#endif
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    int sz = a.size();
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr;
        sz--;
        if(sz) cout << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//#include <atcoder/maxflow>
//using namespace atcoder;
const int inf = (1<<30)-1;
const ll linf = 1LL<<61;
const int MAX = 510000;
int dy[8] = {0,1,0,-1,1,-1,-1,1};
int dx[8] = {-1,0,1,0,1,-1,1,-1};
const double pi = acos(-1);
const double eps = 1e-9;
//const int mod = 1e9 + 7;
const int mod = 998244353;

int main(){
	int n,a,b; cin >> n >> a >> b;
	vl s(n); rep(i,n) cin >> s[i];
	sort(rall(s));
	bool h = true;
	int exor = 0;
	rep(i,n) exor ^= s[i];
	if(a == b){
		exor = 0;
		rep(i,n){
			exor ^= s[i] % (a+1);
		}
		if(exor == 0) h = false;
	}else if(a > b){
		if(s[0] <= b && exor == 0) h = false;
	}else{
		h = false;
		if(s[0] <= a){
			if(exor != 0) h = true;
		}else{
			if(n > 1){
				if(s[1] <= a){
					exor ^= s[0];
					if(s[0] >= exor && s[0]-exor <= a && exor <= a) h = true;
				} 
			}
		}
	}
	if(h) cout << "Hanako\n";
	else cout << "Jiro\n";
}
accuracy: 1
time_ms: 20
memory_kb: 3908
final_rank: 7