Problem:
Problem D
A Bug That's Not a Pill Bug
A bug that looks like a pill bug is walking on a plane.
A Cartesian coordinate system is defined on the plane,
in which its
x-
axis is directed from west to east,
while its
y-
axis is directed from south to north.
The bug is initially at a lattice point (a point where both the
x-
and
y-
coordinates are integers), facing the positive direction of
x.
Obstacles are placed at some of the lattice points on the plane.
The bug continues to move according to the following rules, avoiding obstacles.
The bug attempts to move from its current position to the adjacent lattice point in the direction it is currently facing.
If that adjacent lattice point has no obstacles, the bug moves there without changing its direction.
If that adjacent lattice point has an obstacle, the bug turns 90 degrees to the left, without changing its position.
The initial position of the bug, the locations of the obstacles, and a moving distance are given.
You are requested to find the position of the bug after it has moved exactly the given distance.
Some of the datasets in Sample Input are illustrated below.
The points marked with an "X" indicate the presence of obstacles.
The left figure corresponds to the first two datasets of Sample Input.
In these datasets, the initial position of the bug is (0, 1), and it moves to (1, 1) and then to (2, 1).
Next, it attempts to move to (3, 1), but since there is an obstacle there, it turns to the positive direction of
y
and moves to (2, 2).
The points the bug traverses are shown with orange circles.
The right figure shows the next two datasets.
Figure D-1: The first two datasets of Sample Input (left) and the next two datasets (right)
Input
The input consists of multiple datasets, each in the following format.
The number of datasets does not exceed 200.
n
a
b
d
x
1
y
1
⋮
x
n
y
n
Here,
n
represents the number of obstacles, which is an integer (1 ≤
n
≤ 1000).
Both
a
and
b
are integers between 0 and 100, inclusive, and the initial position of the bug is at coordinates (
a,
b
).
Additionally,
d
represents the distance to move, which is an integer (1 ≤
d
≤ 10
18
).
The
i
-th obstacle is located at coordinates (
x
i
,
y
i
) (
i
= 1, ⋯,
n
).
x
i
and
y
i
are integers between 0 and 100, inclusive.
No two obstacles are at the same location, that is, if
i
≠
j
, then (
x
i
,
y
i
) ≠ (
x
j
,
y
j
).
Additionally, no obstacle is located at the initial position (
a,
b
) of the bug.
It is guaranteed that the bug can move distance
d
or more under the given configuration.
The end of the input is indicated by a line consisting of a zero.
Output
For each dataset, output two integers separated by a space on a single line representing the
x-
and
y-
coordinates of the position of the bug after it has moved distance
d.
Note that the
x-
and
y-
coordinates of the position of the bug can be negative.
Sample Input
2
0 1 4
3 1
2 5
2
0 1 9
3 1
2 5
12
2 2 11
0 1
0 2
0 3
4 1
4 2
4 3
3 4
2 4
1 4
3 0
2 0
1 0
12
2 2 7791772263873
0 1
0 2
0 
...(truncated)

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i, s, t) for (ll i = s; i < (ll)(t); i++)
#define rrep(i, s, t) for(ll i = (ll)(t) - 1; i >= (ll)(s); i--)
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)

#define TT template<typename T>
TT using vec = vector<T>;
template<class T1, class T2> bool chmin(T1 &x, T2 y) { return x > y ? (x = y, true) : false; }
template<class T1, class T2> bool chmax(T1 &x, T2 y) { return x < y ? (x = y, true) : false; }

struct io_setup {
    io_setup() {
        ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        cout << fixed << setprecision(15);
    }
} io_setup;

const int dx[]={1,0,-1,0},dy[]={0,1,0,-1};
const int MAX=100;
const ll INF=1LL<<60;

int main() {
    while(1){
        int N;
        cin>>N;
        if(N==0)return 0;
        int A,B;
        ll D;
        cin>>A>>B>>D;
        vector<int>X(N),Y(N);
        vector flag(MAX+1,vector<bool>(MAX+1));
        rep(i,0,N){
            cin>>X[i]>>Y[i];
            flag[X[i]][Y[i]]=true;
        }
        vector dist(MAX+1,vector(MAX+1,vector<ll>(4,INF)));
        int dir=0;
        dist[A][B][dir]=D;
        while(1){
            int a=A+dx[dir],b=B+dy[dir];
            if(a<0||a>MAX||b<0||b>MAX){
                cout<<A+D*dx[dir]<<" "<<B+D*dy[dir]<<endl;
                break;
            }
            if(flag[a][b]){
                dir=(dir+1)%4;
            }else{
                if(D<=100){
                    A=a,B=b;
                    D--;
                }else{
                    if(dist[a][b][dir]==INF){
                        A=a,B=b;
                        D--;
                        dist[a][b][dir]=D;
                    }else{
                        A=a,B=b;
                        D--;
                        D%=(dist[a][b][dir]-D);
                    }
                }
            }
            if(D==0){
                cout<<A<<" "<<B<<endl;
                break;
            }
        }
    }
}
accuracy: 1
time_ms: 40
memory_kb: 4224
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
// #include <atcoder/all>
// using namespace atcoder;
struct Init {
  Init() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout << setprecision(13);
  }
} init;

using ll = long long;
using ull = unsigned long long;
using VLL = vector<ll>;
using VVLL = vector<VLL>;
using PLL = pair<ll, ll>;
using VS = vector<string>;

#define rep(i, n) for (int i = 0; i < int(n); ++i)
#define FOR(i, a, b) for (int i = int(a); i < int(b); ++i)
#define all(x) (x).begin(), (x).end()
#define rall(x) x.rbegin(), x.rend()
#define el '\n'
#define spa " "
#define Yes cout << "Yes" << el
#define No cout << "No" << el
#define eps (1e-10)
#define Equals(a, b) (fabs((a) - (b)) < eps)
#define debug(x) cerr << #x << " = " << x << el

const double pi = 3.141592653589793238;
const int inf = 1073741823;
const ll infl = 1LL << 60;
const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string abc = "abcdefghijklmnopqrstuvwxyz";
const int dx[4] = {1, 0, -1, 0};
const int dy[4] = {0, 1, 0, -1};

template <typename T>
ostream& operator<<(ostream& os, const vector<T>& v) {
  for (int i = 0; i < (int)v.size(); i++)
    os << v[i] << (i + 1 != (int)v.size() ? " " : "");
  return os;
}
template <typename T>
istream& operator>>(istream& is, vector<T>& v) {
  for (T& in : v)
    is >> in;
  return is;
}
void print() {
  cout << el;
}
template <typename T>
void print(const T& t) {
  cout << t << el;
}
template <typename Head, typename... Tail>
void print(const Head& head, const Tail&... tail) {
  cout << head << spa;
  print(tail...);
}
template <typename T1, typename T2>
inline bool chmax(T1& a, T2 b) {
  bool compare = a < b;
  if (compare)
    a = b;
  return compare;
}
template <typename T1, typename T2>
inline bool chmin(T1& a, T2 b) {
  bool compare = a > b;
  if (compare)
    a = b;
  return compare;
}
void YesNo(bool b) {
  cout << (b ? "Yes" : "No") << el;
}

int main() {
  while (true) {
    ll n, a, b, d;
    cin >> n;
    if (n == 0)
      return 0;
    cin >> a >> b >> d;
    bool block[101][101] = {};
    while (n--) {
      int x, y;
      cin >> x >> y;
      block[x][y] = true;
    }
    ll x = a, y = b, m = 0;
    map<pair<pair<int, int>, int>, ll> ma;
    while (d--) {
      // print("d=", d, "(x, y, m)=", x, y, m);
      if (ma.count({{x, y}, m})) {
        ll c = (ma[{{x, y}, m}] - d);
        d = d % c;
        ma.clear();
      }
      ma[{{x, y}, m}] = d;
      ll nx = x + dx[m];
      ll ny = y + dy[m];
      if (!(0 <= nx && nx <= 100 && 0 <= ny && ny <= 100)) {
        x += (d + 1) * dx[m];
        y += (d + 1) * dy[m];
        break;
      }

      while (block[nx][ny]) {
        m = (m + 1) % 4;
        nx = x + dx[m];
        ny = y + dy[m];
        if (!(0 <= nx && nx <= 100 && 0 <= ny && ny <= 100)) {
          x += (d + 1) * dx[m];
          y += (d + 1) * dy[m];
          break;
        }
      }

      x = nx;
      y = ny;
    }
    print(x, y);
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3880
final_rank: 8

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

const long long MOD1 = 1000000007;
const long long MOD2 = 998244353;
#define all(v) v.begin(), v.end()
#define rall(a) a.rbegin(), a.rend()
#define fi first
#define se second
#define endl "\n"

#define chmax(x, y) x = max(x, y)
#define chmin(x, y) x = min(x, y)

template <typename T>
using vc = vector<T>; // prioriy_queueに必要なのでここにこれ書いてます
template <typename T>
using vv = vc<vc<T>>;
#define int long long
using ll = long long;
ll INF = 2e18;

#ifdef ONLINE_JUDGE
// ジャッジ環境ではデバッグマクロを無効化
#define debug_x(x) \
    do             \
    {              \
    } while (0)
#define debug_vc(v) \
    do              \
    {               \
    } while (0)
#define debug_vv(v) \
    do              \
    {               \
    } while (0)
#else
// ローカルではデバッグ出力
#define debug_x(x) cout << #x << " = " << (x) << endl
#define debug_vc(v)                    \
    {                                  \
        cout << #v << endl;            \
        ll n = size(v);                \
        rep(i, n) cout << v[i] << ' '; \
        cout << endl;                  \
    } // 一次元配列を出力する
#define debug_vv(v)                                        \
    {                                                      \
        cout << #v << endl;                                \
        ll n = size(v);                                    \
        rep(i, n)                                          \
        {                                                  \
            rep(j, size(v[i])) { cout << v[i][j] << ' '; } \
            cout << endl;                                  \
        }                                                  \
    } // 二次元配列を出力する
#endif

#define rep(i, n) for (ll i = 0; i < (n); ++i)
#define rrep(i, n) for (ll i = 1; i <= (n); ++i)
#define drep(i, n) for (ll i = (n) - 1; i >= 0; --i)
#define nfor(i, s, n) for (ll i = s; i < n; i++)        // i=s,s+1...n-1 ノーマルfor
#define dfor(i, s, n) for (ll i = (s) - 1; i >= n; i--) // s-1スタートでnまで落ちる

using ld = long double;
using bl = bool;

template <class T>
using pq = priority_queue<T, vc<T>>; // 大きい順
template <class T>
using pq_g = priority_queue<T, vc<T>, greater<T>>; // 小さい順

using vl = vc<ll>;
using vvl = vv<ll>;
using vvvl = vv<vl>;
using vvvvl = vv<vvl>;
using vs = vc<string>;
using vvs = vv<string>;
using vb = vc<bl>;
using vvb = vv<bl>;
using vvvb = vv<vb>;
using vld = vc<ld>;
using vvld = vv<ld>;
using vvvld = vv<vld>;
using P = pair<ll, ll>;
using vP = vc<P>;
using vvP = vc<vP>;
using vvvP = vv<vP>;

#define pb push_back

#define YES cout << "Yes" << endl
#define NO cout << "No" << endl
#define YN                     \
    {                          \
        cout << "Yes" << endl; \
    }                          \
    else                       \
    {                          \
        cout << "No" << endl;  \
    } // if(a==b)YN;
#define dame cout << -1 << endl

string dir = "DRUL";   // 第4象限の場合
vl di = {1, 0, -1, 0}; // vl di={1,1,0,-1,-1,-1,0,1};
vl dj = {0, 1, 0, -1}; // vl dj={0,1,1,1,0,-1,-1,-1};

bool out_grid(ll i, ll j, ll h, ll w)
{ // trueならcontinue
    return (!(0 <= i && i < h && 0 <= j && j < w));
}

ll n;

void solve()
{
    ll a, b, d;
    cin >> a >> b >> d;
    vl x(n), y(n);
    vvb isBlock(101, vb(101));
    ll ans_i = -1, ans_j = -1;
    rep(i, n)
    {
        cin >> x[i] >> y[i];
        isBlock[x[i]][y[i]] = true;
    }
    vvvl dist(101, vvl(101, vl(4, -1)));
    dist[a][b][0] = 0;
    queue<pair<P, ll>> que;
    que.push({{a, b}, 0});
    if(d==0){
        ans_i = a;
        ans_j = b;
        que = {};
    }
    while (!que.empty())
    {
        auto [co, cur_dir] = que.front();
        auto [i, j] = co;
        que.pop();
        ll ni = i + di[cur_dir];
        ll nj = j + dj[cur_dir];
        if (out_grid(ni, nj, 101, 101))
        {
            // ループしないで場外へ
            // cout << "ループしない" << endl;
            ll rest = d - dist[i][j][cur_dir];
            ans_i = i + rest * di[cur_dir];
            ans_j = j + rest * dj[cur_dir];
        }
        else
        {
            if (isBlock[ni][nj])
            {
                ll nex_dir = (cur_dir + 1) % 4;
                if (dist[i][j][nex_dir] == -1)
                {
                    dist[i][j][nex_dir] = dist[i][j][cur_dir];
                    if(dist[i][j][nex_dir] == d){
                        ans_i = i;
                        ans_j = j;
                        break;
                    }
                    else{
                        que.push({co, nex_dir});
                    }
                }
                else
                {
                    // cout << "ループする(方向転換)" << endl;
                    // ループする
                    ll span = dist[i][j][cur_dir] - dist[i][j][nex_dir];
                    ll rest = d - dist[i][j][cur_dir];
                    ll amari = rest % span;
                    rep(ii, 101)
                    {
                        rep(jj, 101)
                        {
                            rep(k, 4)
                            {
                                if ((dist[ii][jj][k] - dist[i][j][nex_dir])>=0&&(dist[ii][jj][k] - dist[i][j][nex_dir]) % span == amari)
                                {
                                    ans_i = ii;
                                    ans_j = jj;
                                }
                            }
                        }
                    }
                    break;
                }
            }
            else
            {
                if (dist[ni][nj][cur_dir] == -1)
                {
                    dist[ni][nj][cur_dir] = dist[i][j][cur_dir] + 1;
                    if(dist[ni][nj][cur_dir] == d){
                        ans_i = ni;
                        ans_j = nj;
                    }
                    else{
                        que.push({{ni, nj}, cur_dir});
                    }
                }
                else
                {
                    // ループする
                    // cout << "ループする(移動)" << endl;
                    ll span = dist[i][j][cur_dir] - dist[ni][nj][cur_dir] + 1;
                    ll rest = d - dist[i][j][cur_dir];
                    ll amari = rest % span;
                    rep(ii, 101)
                    {
                        rep(jj, 101)
                        {
                            rep(k, 4)
                            {
                                if ((dist[ii][jj][k] - dist[ni][nj][cur_dir])>=0&&(dist[ii][jj][k] - dist[ni][nj][cur_dir] + 1) % span == amari)
                                {
                                    ans_i = ii;
                                    ans_j = jj;
                                }
                            }
                        }
                    }
                    break;
                }
            }
        }
    }
    cout << ans_i << ' ' << ans_j << endl;
    return;
}

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    while (true)
    {
        cin >> n;
        if (n == 0)
            break;
        solve();
    }
    return 0;
}

/*
shift+alt+Fで成形
f2で変数名変更

スニペット
basic
 m:atcoder以外用
 ma:ABC/ARC用
 mahc:AHC用
math
 floor:床関数
 ceil:天井関数
 comv:二項係数
 modpow: a^b mod m
 GCD:最大公約数
 extGCD:拡張ユークリッド互除法
 PFD:素因数分解
 isprime:エラトステネスの篩
 matrixpow:行列累乗
data_structure
 seg:セグメント木
technic
 Compress:座標圧縮
 runlength:ランレングス圧縮
graph
 warshall:ワーシャルフロイド法
 dfs:深さ優先探索
 bfs:幅優先探索
 LCA:最近共通祖先
*/
accuracy: 1
time_ms: 60
memory_kb: 4240
final_rank: 15

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

bool solve(){
    int n;
    cin >> n;
    if(n == 0) return false;

    int a,b;
    ll d;
    cin >> a >> b >> d;

    vector<vector<bool>> block(101,vector<bool>(101,false));
    rep(i,n){
        int x,y;
        cin >> x >> y;
        block[x][y] = true;
    }


    int dx[] = {1,0,-1,0};
    int dy[] = {0,1,0,-1};
    ll cx = a;
    ll cy = b;
    vector<vector<vector<ll>>> seen(101,vector<vector<ll>>(101,vector<ll>(4,-1)));
    bool r = false;
    int dir = 0;
    while(d){
        if(
            0 <= cx+dx[dir] && cx+dx[dir] <= 100 &&
            0 <= cy+dy[dir] && cy+dy[dir] <= 100 &&
            block[cx+dx[dir]][cy+dy[dir]]
        ){
            dir++;
            dir %= 4;
            // cout << "?";
        }else{
            cx += dx[dir];
            cy += dy[dir];
            d--;
            if(
                cx + dx[dir] < 0 ||
                100 < cx + dx[dir] ||
                cy + dy[dir] < 0 ||
                100 < cy + dy[dir]
            ){
                cx += dx[dir] * d;
                cy += dy[dir] * d;
                break;
            }
            // cout << "a";
        }
        ll dd = seen[cx][cy][dir];
        if(dd != -1 && !r){
            ll ddd = dd - d;
            d %= ddd;
            r = true;
            // cout << "!";
        }
        seen[cx][cy][dir] = d;
        // cout << cx << ":" << cy << endl;
    }

    cout << cx << " " << cy << endl;

    return true;
}

int main(){
    while(solve()){
    }
}
accuracy: 1
time_ms: 70
memory_kb: 4096
final_rank: 13

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,N) for(i=0;i<N;i++)
#define ll long long

typedef struct _pos{
    ll x,y;
}pos;
pos operator+(pos a,pos b){
    return {a.x+b.x,a.y+b.y};
}
pos pos_move[4]={{1,0},{0,1},{-1,0},{0,-1}};

bool is_out(pos next){
    return (next.x<0 || 100<next.x || next.y<0 || 100<next.y);
}

int main(void){
    ll i,j,k;

    ll N;
    ll A,B,D;

    for(;;){
        cin>>N;
        if(N==0)break;
        cin>>A>>B>>D;

        bool wall[109][109]={0};
        ll vis[109][109][4];
        rep(i,109)rep(j,109)rep(k,4)vis[i][j][k]=-1;

        rep(i,N){
            ll x,y;
            cin>>x>>y;
            wall[x][y]=1;
        }

        pos now={A,B};
        ll d=0;
        vis[A][B][d]=0;
        while(D!=0){
            D--;
            pos next=now+pos_move[d];

            ll now_vis=vis[now.x][now.y][d];
            while(!is_out(next)){
                if(!wall[next.x][next.y])break;
                d=(d+1)%4;
                next=now+pos_move[d];
            }
            if(is_out(next)){
                next.x+=pos_move[d].x*D;
                next.y+=pos_move[d].y*D;
                now=next;
                break;
            }

            if(vis[next.x][next.y][d]!=-1){
                ll roop=now_vis+1-vis[next.x][next.y][d];
                // clog<<"roop:"<<roop<<" ("<<next.x<<","<<next.y<<")"<<endl;
                D%=roop;
            }
            vis[next.x][next.y][d]=now_vis+1;
            now=next;
        }

        cout<<now.x<<" "<<now.y<<endl;
        if(now.x==-3 && now.y==72){
            clog<<N<<" "<<A<<" "<<B<<endl;
        }
    }

    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3588
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
int main(){
    int n;
    vector<pair<long long,long long>> lastans;
    while(true){
        cin >> n;
        if(n == 0) break;
        int a,b;
        long long d;
        cin >> a >> b >> d;
        map<pair<int,int>,bool> block;
        for(int i = 0; i < n; i++) {
            int x,y;
            cin >> x >> y;
            block[{x,y}] = true;
        }
        vector<pair<pair<long long,long long>,int>> path;
        map<vector<long long>,bool> visited;
        long long x =a, y = b, z=0,count=0;
        bool nx=false, ny=false,px=false,py=false,flag=false,flag2=false;
        vector<pair<int,int>> dir = {{1,0},{0,1},{-1,0},{0,-1}};
        while(true){
             if(count == d) {
                lastans.push_back({x,y});
                break;
            }
            if(visited[{x,y,z}]){
                flag = true;
                break;
            }
            if(x>100&&z!=2){
                flag2=true;
                break;
            }
            if(y>100&&z!=3){
                flag2=true;
                break;
            }
            if(x<0&&z!=0){
                flag2 = true;
                break;
            }
            if(y<0&&z!=1){
                flag2 = true;
                break;
            }
            visited[{x,y,z}] = true;
            path.push_back({{x,y},z});
            count++;
            for(int i=0;i<4;i++){
                int dx = dir[z].first, dy = dir[z].second;
                if(!block[{x+dx,y+dy}]) {
                    x += dx;
                    y += dy;
                    break;
                }
                z ++;
                z %= 4;
            }
        }
        if(flag2){
            int dx= dir[z].first, dy = dir[z].second;
            lastans.push_back({x+dx*(d-count),y+dy*(d-count)});
        }else if(flag){
            long long index = 0;
            for(int i=0;i<count;i++){
                pair<long long,long long> p=make_pair(x,y);
                if(path[i].first==p&&path[i].second==z){
                    break;
                }
                index++;
            }
            d-= index;
            d%=(count-index);
            lastans.push_back(path[index+d].first);
        }
    }   
    for(int i = 0; i < lastans.size(); i++) {
        cout << lastans[i].first <<" "<< lastans[i].second<< endl;
    }
}
accuracy: 1
time_ms: 40
memory_kb: 4404
final_rank: 12

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);(i)<(b);(++i))
using ll=long long;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){return a>b?a=b,true:false;}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){return a<b?a=b,true:false;}

int main(){
    cin.tie(nullptr)->ios::sync_with_stdio(false);
    while(true){
        ll n;
        cin>>n;
        if(n==0) return 0;
        ll a,b,d;
        cin>>a>>b>>d;
        vector<int> x(n),y(n);
        set<pair<int,int>> block;
        rep(i,0,n){
            cin>>x[i]>>y[i];
            block.insert({x[i],y[i]});
        }
        const int N=101;
        const ll inf=1ll<<60;
        const int dy[]={0,1,0,-1};
        const int dx[]={1,0,-1,0};
        vector dist(N,vector(N,vector<ll>(4,inf)));
        ll nowX=a,nowY=b;
        int dir=0;
        dist[nowX][nowY][dir]=0;
        rep(turn,0,d){
            const ll nowval=dist[nowX][nowY][dir];
            ll neX=nowX+dx[dir];
            ll neY=nowY+dy[dir];
            while(block.contains({neX,neY})){
                dir++;
                if(dir==4) dir-=4;
                neX=nowX+dx[dir];
                neY=nowY+dy[dir];
            }
            if(neX<0 or 100<neX or neY<0 or 100<neY){
                ll remD=d-turn-1;
                neX+=dx[dir]*remD;
                neY+=dy[dir]*remD;
                nowX=neX;
                nowY=neY;
                break;
            }
            // has loop
            if(dist[neX][neY][dir]!=inf){
                const ll len=nowval+1-dist[neX][neY][dir];
                if(len==0){
                    nowX=neX;
                    nowY=neY;
                    break;
                }
                ll ansD=(d-turn-1)%len;
                ll X=neX;
                ll Y=neY;
                ll ndir=dir;
                while(ansD--){
                    ll nX=X+dx[ndir];
                    ll nY=Y+dy[ndir];
                    while(block.contains({nX,nY})){
                        ndir++;
                        if(ndir==4) ndir-=4;
                        nX=X+dx[ndir];
                        nY=Y+dy[ndir];
                    }
                    X=nX;
                    Y=nY;
                }
                nowX=X;
                nowY=Y;
                break;
            }else{
                dist[neX][neY][dir]=nowval+1;
                nowX=neX;
                nowY=neY;
            }
        }
        cout<<nowX<<" "<<nowY<<"\n";
    }
}
accuracy: 1
time_ms: 50
memory_kb: 4352
final_rank: 14

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pll pair<ll,ll>
#define vll vector<ll>
#define rep(i,n) for(int i = 0;i < (n);i++)
#define fore(e,v) for(auto &&e : v)
#define all(a) begin(a), end(a)
#define si(a) (int)(a.size())
#define lb(v,x) (lower_bound(all(v),x) - begin(v))
#define eb emplace_back

template<typename T,typename S> bool chmin(T& a, const S& b){
	return a > b ? a = b,1 : 0;
}
template<typename T,typename S> bool chmax(T& a, const S& b){
	return a < b ? a = b,1 : 0;
}
const ll inf = 3e18;
struct _{
	_(){ cin.tie(0) -> sync_with_stdio(0), cout.tie(0);}
}__;

ll dx[] = {1,0,-1,0};
ll dy[] = {0,1,0,-1};

int main(){
	while(1){
		ll n;
		cin>>n;
		if(n == 0) break;
		ll a,b,d;
		cin>>a>>b>>d;
		const ll M = 101;
		vector<int> x_y[M],y_x[M];
		rep(i,n){
			ll x,y;
			cin>>x>>y;
			x_y[x].eb(y);
			y_x[y].eb(x);
		}
		rep(i,M){
			sort(all(x_y[i]));
			sort(all(y_x[i]));
		}
		ll rem[M][M][4];
		rep(i,M)rep(j,M)rep(r,4)rem[i][j][r] = -1;
		queue<pair<ll,pll> > que;
		auto push = [&](ll x,ll y,ll r){
			if(rem[x][y][r] > d){
				ll shuki = rem[x][y][r] - d;
				d %= shuki;
			}else{
				rem[x][y][r] = d;
			}
			que.push(make_pair(r,make_pair(x,y)));
		};
		push(a,b,0);
		while(!que.empty()){
			auto [r,xy] = que.front();
			auto [x,y] = xy;
			que.pop();
			// cout<<"x,y,r = "<<x<<" "<<y<<" "<<r<<endl;
			ll nx = -1,ny = -1, dd = 0;
			if(r == 0){
				ll j = lb(y_x[y],x + 1);
				if(j == si(y_x[y])){
					dd = d;
				}
				else{
					dd = y_x[y][j] - 1 - x;
				}
			}else if(r == 1){
				ll j = lb(x_y[x],y + 1);
				if(j == si(x_y[x])){
					dd = d;
				}else{
					dd = x_y[x][j] - 1 - y;
				}
			}else if(r == 2){
				ll j = lb(y_x[y],x);
				if(j == 0){
					dd = d;
				}else{
					dd = x - (y_x[y][j - 1] + 1);
				}
			}else if(r == 3){
				ll j = lb(x_y[x],y);
				if(j == 0){
					dd = d;
				}else{
					dd = y - (x_y[x][j - 1] + 1);
				}
			}
			chmin(dd,d);
			d -= dd;
			nx = x + dx[r] * dd;
			ny = y + dy[r] * dd;
			if(d > 0){
				push(nx,ny,(r + 1) % 4);
			}else{
				cout<<nx<<" "<<ny<<endl;
			}
		}
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3740
final_rank: 4

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

int di[]={1,0,-1,0};
int dj[]={0,1,0,-1};

void solve(int n){
    ll a,b,d; cin>>a>>b>>d;
    vector g(101,vector<int>(101));
    rep(i,n){
        int x,y; cin>>x>>y;
        g[x][y]=1;
    }

    ll ansx,ansy;
    vector visited(101,vector(101,vector<ll>(4,-1)));
    ll i=a,j=b,k=0;
    while(1){
        if(visited[i][j][k]!=-1){
            d=d%(visited[i][j][k]-d);
            if(d==0){
                ansx=i;
                ansy=j;
                break;
            }
        }
        visited[i][j][k]=d;

        ll nexti=i+di[k];
        ll nextj=j+dj[k];

        if(nexti<0 || nextj<0 || nexti>=101 || nextj>=101){
            ansx=i+di[k]*d;
            ansy=j+dj[k]*d;
            break;
        }

        if(g[nexti][nextj]==1){
            k=(k+1)%4;
            continue;
        }

        i=nexti;
        j=nextj;
        d--;

        if(d==0){
            ansx=i;
            ansy=j;
            break;
        }
    }
    cout << ansx << " " << ansy << endl;
}

int main(){
    while(1){
        int n; cin>>n;
        if(n==0) break;
        solve(n);
    }
    return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 4224
final_rank: 10

code_snippet: #include <bits/stdc++.h>
int N;
long long A, B, D, X[1000], Y[1000];
const int dx[]{1,0,-1,0},dy[]{0,1,0,-1};
void solve() {
    std::set<std::pair<long long, long long>> blk;
    for (int i = 0 ; i < N ; i++) blk.insert({X[i], Y[i]});
    std::set<std::tuple<long long, long long, int>> set;
    int dir = 0;
    auto next_step = [&]() -> std::optional<std::pair<long long, long long>> {
        long long a = A, b = B;
        for (long long i = 0 ; i < std::min(120LL, D) ; i++) {
            const long long na = a + dx[dir], nb = b + dy[dir];
            if (blk.contains({na, nb})) {
                return std::pair{a, b};
            }
            a = std::move(na);
            b = std::move(nb);
        }
        return std::nullopt;
    };
    std::stack<std::pair<
        std::tuple<long long, long long, int>,
        long long>> stk;
    stk.push(std::pair{std::tuple{A, B, dir}, 0LL});
    set.insert({A, B, dir});
    bool fn = false;
    while (D) {
        assert(D > 0);
        const auto npos = next_step();
        if (npos) {
            const auto [na, nb] = npos.value();
            const long long d = std::abs(A - na) + std::abs(B - nb);
            D -= d;
            dir = (dir + 1) % 4;
            A = na;
            B = nb;
            if (!fn and set.contains({A, B, dir})) {
                fn = true;
                long long cyc = d; 
                while (true) {
                    assert(stk.size());
                    if (stk.top().first == std::tuple{A, B, dir}) break;
                    cyc += stk.top().second;
                    stk.pop();
                }
                assert(cyc > 0);
                D %= cyc;
            }
            else {
                stk.push(std::pair{std::tuple{A, B, dir}, d});
                set.insert({A, B, dir});
            }
        }
        else {
            A += D * dx[dir];
            B += D * dy[dir];
            D = 0;
            break;
        }
    }
    std::cout << A << ' ' << B << '\n';
}
int main() {
    while (true) {
        std::cin >> N;
        if (N == 0) break;
        std::cin >> A >> B >> D;
        for (int i = 0 ; i < N ; i++) std::cin >> X[i] >> Y[i];
        solve();
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3584
final_rank: 1

code_snippet: #include <iostream>
#include <array>

void calc(int n) {
  int r = 0;
  std::int64_t a, b, d;
  std::cin >> a >> b >> d;
  std::array<std::array<bool, 101>, 101> obs{false};
  std::array<std::array<std::array<std::int64_t, 4>, 101>, 101> dist{};
  
  dist[b][a][r] = d;
  
  std::array<int, 4> mvx = { 1, 0, -1, 0};
  std::array<int, 4> mvy = { 0, 1, 0, -1};
  
  for (int i = 0; i < n; ++i) {
    int x, y;
    std::cin >> x >> y;
    obs[y][x] = true;
  }
  
  bool cycleFound = false;
  
  while (d) {
    int A, B;
    A = a + mvx[r];
    B = b + mvy[r];
    if ((A < 0 || 100 < A) || (B < 0 || 100 < B)) {
      a += d * mvx[r];
      b += d * mvy[r];
      d = 0;
      break;
    }
    if (obs[B][A]) {
      ++r;
      r = ((r % 4) + 4) % 4;
    } else {
      a = A;
      b = B;
      --d;
      if (dist[b][a][r] > 0 && !cycleFound) {
        int cycleDist = dist[b][a][r] - d;
        d %= cycleDist;
        cycleFound = true;
      }
      dist[b][a][r] = d;
    }
  }
  std::cout << a << ' ' << b << std::endl;
}

int main() {
  int n;
  
  while (true) {
    std::cin >> n;
    if (n == 0) {
      break;
    }
    calc(n);
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3652
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
template <class T>
using MaxHeap = std::priority_queue<T>;
template <class T>
using MinHeap = std::priority_queue<T, vector<T>, greater<T>>;
#define rep2(i, n) for (ll i = 0; i < (n); i++)
#define rep3(i, l, r) for (ll i = (l); i < (r); i++)
#define rrep2(i, n) for (ll i = n; i-- > 0;)
#define rrep3(i, r, l) for (ll i = (r); i-- > (l);)
#define overload(a, b, c, d, ...) d
#define rep(...) overload(__VA_ARGS__, rep3, rep2)(__VA_ARGS__)
#define rrep(...) overload(__VA_ARGS__, rrep3, rrep2)(__VA_ARGS__)
#define all(x) begin(x), end(x)
bool chmin(auto& lhs, auto rhs) {
    return lhs > rhs ? lhs = rhs, 1 : 0;
}
bool chmax(auto& lhs, auto rhs) {
    return lhs < rhs ? lhs = rhs, 1 : 0;
}
struct IOIO {
    IOIO() {
        std::cin.tie(0)->sync_with_stdio(0);
    }
} ioio;

void solve() {
    while (true) {
        int n;
        cin >> n;
        if (n == 0) return;
        const int N = 103;
        const int OFFSET = 1;
        vector parent(N, vector(N, vector<tuple<int, int, int>>(4)));
        int si, sj;
        ll d;
        cin >> sj >> si >> d;
        si += OFFSET;
        sj += OFFSET;
        vector obs(N, vector<int>(N));
        rep(i, n) {
            ll x, y;
            cin >> x >> y;
            x += OFFSET;
            y += OFFSET;
            obs[y][x] = true;
        }
        const int DI[] = {1, 0, -1, 0};
        const int DJ[] = {0, -1, 0, 1};
        rep(i, N) rep(j, N) rep(d, 4) {
            parent[i][j][d] = {i, j, d};
            if (obs[i][j]) continue;
            if (i == 0 || j == 0 || i == N - 1 || j == N - 1) continue;
            rep(dd, 4) {
                int nd = (d + dd) % 4;
                int ni = i + DI[nd];
                int nj = j + DJ[nd];
                if (ni < 0 || nj < 0 || ni >= N || nj >= N) continue;
                if (obs[ni][nj]) continue;
                parent[i][j][d] = {ni, nj, nd};
                break;
            }
        }
        const int LOG = 60;
        vector to(LOG + 1, vector(N, vector(N, vector<tuple<int, int, int>>(4))));
        rep(i, N) rep(j, N) rep(k, 4) to[0][i][j][k] = parent[i][j][k];
        rep(log, LOG) {
            rep(i, N) rep(j, N) rep(k, 4) {
                auto [a, b, c] = to[log][i][j][k];
                to[log + 1][i][j][k] = to[log][a][b][c];
            }
        }
        tuple<ll, ll, ll> pos = {si, sj, 3};
        rep(i, LOG + 1) {
            if (d & (1LL << i)) {
                auto [a, b, c] = pos;
                pos = to[i][a][b][c];
            }
        }
        {
            tuple<ll, ll, ll> pos = {si, sj, 3};
            rep(i, min<ll>(d, 20)) {
                auto [a, b, c] = pos;
                pos = to[0][a][b][c];
                //  cerr << a << ' ' << b << ' ' << c << endl;
            }
        }
        auto [i, j, dir] = pos;
        if (i == 0 || j == 0 || i == N - 1 || j == N - 1) {
            //  i = 0, or j = 0 or ...になる最小時間
            ll ok = 1e18;
            ll ng = 0;
            while (ok - ng > 1) {
                ll key = (ok + ng) / 2;
                tuple<ll, ll, ll> pos = {si, sj, 3};
                rep(i, LOG + 1) {
                    if (key & (1LL << i)) {
                        auto [a, b, c] = pos;
                        pos = to[i][a][b][c];
                    }
                }
                auto [i, j, _] = pos;
                if (i == 0 || j == 0 || i == N - 1 || j == N - 1)
                    ok = key;
                else
                    ng = key;
            }
            //  cerr << d << ' ' << d - ok << endl;
            d -= ok;
            assert(d >= 0);
            i += d * DI[dir];
            j += d * DJ[dir];
            cout << j - OFFSET << ' ' << i - OFFSET << '\n';
        } else {
            //  cerr << __LINE__ << endl;
            cout << j - OFFSET << ' ' << i - OFFSET << '\n';
        }
    }
}

int main() {
    int t = 1;
    //  cin >> t;
    while (t--) solve();
}
accuracy: 1
time_ms: 5510
memory_kb: 61184
final_rank: 19

code_snippet: #include<bits/stdc++.h>
#define fast std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::cout.tie(nullptr)
#define eb emplace_back
#define mp make_pair
#define all(x) (x).begin(), (x).end()
using namespace std;
using ll = long long;
constexpr ll inf = 2e18;
constexpr int mod = 998244353;
#ifdef LOCAL
#define debug(x) std::cerr << #x << " = " << (x) << std::endl;
#else
#define debug(x)
#endif
static void judge(bool c) {
    std::cout << (c ? "Yes" : "No") << '\n';
}

ll n,a,b,d,x[1000],y[1000];
ll dirx[4] = {1,0,-1,0},diry[4] = {0,1,0,-1};
set<pair<ll,ll>> hit; 

int main() {
    fast;
    while(true){ 
        cin >> n;
        if(n == 0) return 0; 

        cin >> a >> b >> d;
        hit.clear(); 
        for(int i = 0; i < n; i++) {
            ll obs_x, obs_y;
            cin >> obs_x >> obs_y;
            hit.insert(mp(obs_x, obs_y));
        }

        ll nowx = a, nowy = b;
        ll dir = 0; 
        
        vector<tuple<ll,ll,ll>> path_log;
        map<tuple<ll,ll,ll>, ll> visited_step;

        path_log.eb(make_tuple(nowx, nowy, dir));
        visited_step[make_tuple(nowx, nowy, dir)] = 0; 

        ll current_step = 0; 

        bool loop_detected = false;
        ll loop_start_step = -1; 
        ll loop_length = -1; 

        const ll SIMULATION_LIMIT = 200000; 

        for(ll i = 0; i < SIMULATION_LIMIT; ++i) { 
            ll next_x = nowx + dirx[dir];
            ll next_y = nowy + diry[dir];

            if(hit.count(mp(next_x, next_y))) { 
                dir = (dir + 1) % 4; 
            } else { 
                nowx = next_x;
                nowy = next_y;
                current_step++; 
                
                if (visited_step.count(make_tuple(nowx, nowy, dir))) {
                    loop_detected = true;
                    loop_start_step = visited_step[make_tuple(nowx, nowy, dir)];
                    loop_length = current_step - loop_start_step; 
                    break;
                }
                
                path_log.eb(make_tuple(nowx, nowy, dir));
                visited_step[make_tuple(nowx, nowy, dir)] = current_step;
            }

            if (current_step >= d) {
                break;
            }
        }

        if (loop_detected) {
            if (d < current_step) {
                auto final_state = path_log[d];
                cout << get<0>(final_state) << " " << get<1>(final_state) << endl;
            } else {
                ll remaining_d = d - loop_start_step;
                ll offset_in_loop = remaining_d % loop_length;
                
                auto final_state = path_log[loop_start_step + offset_in_loop];
                cout << get<0>(final_state) << " " << get<1>(final_state) << endl;
            }
        } else {
            if (current_step >= d) {
                auto final_state = path_log[d];
                cout << get<0>(final_state) << " " << get<1>(final_state) << endl;
            } else {
                ll remaining_move = d - current_step;
                nowx += dirx[dir] * remaining_move;
                nowy += diry[dir] * remaining_move;
                cout << nowx << " " << nowy << endl;
            }
        }
    }
}
accuracy: 1
time_ms: 2350
memory_kb: 25208
final_rank: 18

code_snippet: // #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
// #include <atcoder/all>
using namespace std;
// using namespace atcoder;
#define rep(i, a, b) for(int i = (a); i < (b); i++) // [a, b)を昇順に
#define drep(i, a, b) for(int i = (b) - 1; i >= a; i--) // [a, b)を降順に
#define all(v) v.begin(), v.end() // 昇順sortに
#define rall(v) v.rbegin(), v.rend() // 降順sortに
#define sz(x) (int)(x).size()
#define decimal(n) cout << fixed << setprecision(n);
#define debug(x) cerr << #x << " = " << x << endl;
#define Yes cout << "Yes" << endl;
#define No cout << "No" << endl;
#define yesno(condition) { if (condition) cout << "Yes" << endl; else cout << "No" << endl; }
using vi = vector<int>; using vvi = vector<vi>; using vs = vector<string>;
using ll = long long; using vl = vector<ll>; using vvl = vector<vl>; using vvvl = vector<vvl>;
using lll = __int128;
// using mint = modint998244353;
const ll MOD = 998244353;
// using mint = modint;
// const ll MOD = 998244353;
// using mint = modint1000000007;
// const ll MOD = 1000000007;
// using vm = vector<mint>; using vvm = vector<vm>; using vvvm = vector<vvm>;
using P = pair<ll, ll>; using T = tuple<ll, ll, ll>;
using vc = vector<char>;
const ll MAX = 5'000'009; const ll llINF = 2e18;
const int intINF = 2e9; const long double pi = acos(-1);
ll di[] = {0, -1, 0, 1, -1, -1, 1, 1};
ll dj[] = {1, 0, -1, 0, 1, -1, -1, 1};
template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }
template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }
template<class T> using pq = priority_queue<T, vector<T>>; //大きい順
template<class T> using pq_g = priority_queue<T, vector<T>, greater<T>>; //小さい順

bool isin(ll i, ll j, ll n, ll m) { return (0 <= i && i < n && 0 <= j && j < m); }
bool is_multipul_overflow(ll a, ll b, ll c) {
    // a * b > cかを判定する
    if (a == 0 || b == 0) return false;
    return (a <= c / b ? false : true);
}



ll dx[] = {1, 0, -1, 0};
ll dy[] = {0, 1, 0, -1};

void solve(ll &n) {
    ll a, b, d;
    cin >> a >> b >> d;
    vl x(n), y(n);
    rep(i, 0, n) cin >> x[i] >> y[i];
    set<P> isblocked;
    rep(i, 0, n) {
        isblocked.insert({x[i], y[i]});
    }

    int mincoordinate = -1, maxcoordinate = 101;
    // x,yともに-1以下、101以上を超えたらその方向にまっすぐ進む
    // 前と同じ座標、同じ方向にたどり着いたらループしている

    auto dist = vector(maxcoordinate, vector(maxcoordinate, vector<int>(4, intINF)));
    ll rundist = 0;
    ll curx = a, cury = b, curdir = 0;

    // dist[curx][cury][curdir] = 0;

    while(rundist < d) {
        // 障害物に当たりえない範囲に来たので、残りの距離だけその方向に進む
        if(min(curx, cury) <= mincoordinate || max(curx, cury) >= maxcoordinate) {
            curx += (d - rundist) * dx[curdir];
            cury += (d - rundist) * dy[curdir];

            rundist += d - rundist;
            continue;
        }
        // 前と同じ座標、同じ方向に来たので、ループ分を飛ばす
        else if(dist[curx][cury][curdir] != intINF && d- rundist >= rundist - dist[curx][cury][curdir]) {
            ll loopdist = rundist - dist[curx][cury][curdir];

            // dを超えない範囲で、rundistにloopdistを足し続ける
            rundist += loopdist * ((d - rundist) / loopdist);
            continue;
        }

        // 距離を記録しておく
        dist[curx][cury][curdir] = rundist;


        ll nextx = curx + dx[curdir], nexty = cury + dy[curdir];

        // 次に障害物がないので、進む
        if(!isblocked.count({nextx, nexty})) {

            rundist++;

            swap(nextx, curx);
            swap(nexty, cury);
        }
        // 次に障害物があるので、回転する
        else {
            curdir++;
            if(curdir == 4) curdir = 0;
        }
    }

    cout << curx << " " << cury << endl;
}

int main() {
    ll n;
    while(true) {
        cin >> n;
        if(n == 0) break;
        solve(n);
    }
}
accuracy: 1
time_ms: 80
memory_kb: 3868
final_rank: 11

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

void solve(int N) {
    int a, b;
    ll d;
    cin >> a >> b >> d;
    vector<vector<bool>> obj(101, vector<bool>(101, false));
    for (int i=0; i<N; i++) {
        int x, y;
        cin >> x >> y;
        obj[x][y] = true;
    }

    int dir = 0;
    int dirx[] = {1,0,-1,0};
    int diry[] = {0,1,0,-1};

    struct S {
        int right, up, left, down;
    };
    vector<vector<S>> dist(101, vector<S>(101, {-1,-1,-1,-1}));
    dist[a][b].right = 0;
    vector<tuple<int, int, S>> hist;
    hist.emplace_back(make_tuple(a, b, dist[a][b]));

    int x=a, y=b;
    int count = 0;
    while (true) {
        count++;
        int nx = x+dirx[dir], ny = y+diry[dir];
        while (0<=nx && nx<=100 && 0<=ny && ny<=100 && obj[nx][ny]) {
            // turn 90
            dir = (dir+1)%4;
            nx = x+dirx[dir]; ny = y+diry[dir];
        }
        //cerr << '(' << nx << ',' << ny << ")\n";
        if (nx<0 || 101<=nx || ny<0 || 101<=ny) {
            // get out
            ll fx = x + (d-count+1) * dirx[dir];
            ll fy = y + (d-count+1) * diry[dir];
            cout << fx << ' ' << fy << endl;
            return;
        }
        if (dir == 0) {
            if (dist[nx][ny].right != -1) {
                int loop_len = count - dist[nx][ny].right;
                int res = (d - count) % loop_len;
                int fx = get<0>(hist[dist[nx][ny].right+res]);
                int fy = get<1>(hist[dist[nx][ny].right+res]);
                cout << fx << ' ' << fy << endl;
                return;
            }
            dist[nx][ny].right = count;
        }
        else if (dir == 1) {
            if (dist[nx][ny].up != -1) {
                int loop_len = count - dist[nx][ny].up;
                int res = (d - count) % loop_len;
                int fx = get<0>(hist[dist[nx][ny].up+res]);
                int fy = get<1>(hist[dist[nx][ny].up+res]);
                cout << fx << ' ' << fy << endl;
                return;
            }
            dist[nx][ny].up = count;
        }
        else if (dir == 2) {
            if (dist[nx][ny].left != -1) {
                int loop_len = count - dist[nx][ny].left;
                int res = (d - count) % loop_len;
                int fx = get<0>(hist[dist[nx][ny].left+res]);
                int fy = get<1>(hist[dist[nx][ny].left+res]);
                cout << fx << ' ' << fy << endl;
                return;
            }
            dist[nx][ny].left = count;
        }
        else {
            if (dist[nx][ny].down != -1) {
                int loop_len = count - dist[nx][ny].down;
                int res = (d - count) % loop_len;
                int fx = get<0>(hist[dist[nx][ny].down+res]);
                int fy = get<1>(hist[dist[nx][ny].down+res]);
                cout << fx << ' ' << fy << endl;
                return;
            }
            dist[nx][ny].down = count;
        }
        hist.emplace_back(make_tuple(nx, ny, dist[nx][ny]));
        x = nx; y = ny;

        if (count == d) break;
    }

    cout << x << ' ' << y << endl;
}

int main() {
    while(true) {
        int N;
        cin >> N;
        if (N == 0) break;
        solve(N);
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3840
final_rank: 7

code_snippet: #line 1 "D.cpp"
#include <iostream>
#include <utility>
#include <vector>
#include <cassert>
using namespace std;
using ll = long long;
template<class T> inline bool chmax(T& a, const T& b) {if (a<b) {a=b; return true;} return false;}
template<class T> inline bool chmin(T& a, const T& b) {if (b<a) {a=b; return true;} return false;}
constexpr int INTINF = 1000001000;
constexpr int INTMAX = 2147483647;
constexpr ll LLMAX = 9223372036854775807;
constexpr ll LLINF = 4450000000011100000;

#line 1 "/home/harui/CompetitiveProgramming/library/debug.hpp"



#ifdef LOCAL
#define dbg(x) std::cerr << __LINE__ << " : " << #x << " = " << (x) << std::endl
#else
#define dbg(x) true
#endif

#line 13 "/home/harui/CompetitiveProgramming/library/debug.hpp"
#include <set>


template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
  os << '(' << p.first << ", " << p.second << ')';
  return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {
  os << '[';
  for (int i=0; i<int(vec.size()); i++) {
    os << vec[i];
    if (i != int(vec.size())-1) os << ", ";
  }
  os << ']';
  return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& st) {
  os << '{';
  auto itr = st.begin();
  while (itr != st.end()) {
    os << *itr;
    itr = next(itr);
    if (itr != st.end()) os << ", ";
  }
  os << '}';
  return os;
}



#line 15 "D.cpp"

const int dx[4] = {1,0,-1,0};
const int dy[4] = {0,1,0,-1};

bool isin(int x, int y) {
  return 0 <= x && x <= 100 && 0 <= y && y <= 100;
}

int moove (vector<vector<vector<vector<int>>>>const& dp, int x, int y, int k, ll num) {
  assert(isin(x,y));
  assert(0 <= k && k < 4);

  dbg(num);
  for (int i=0; i<60 && (1LL<<i)<=num && num > 0; i++) {
    if ((1LL << i) & num) {
      int nxt_val = dp[i][k][x][y];
      if (nxt_val >= INTINF) return nxt_val;
      int nxt_k = nxt_val / 10201;
      int nxt_x = nxt_val % 10201 / 101;
      int nxt_y = nxt_val % 10201 % 101;

      k = nxt_k;
      x = nxt_x;
      y = nxt_y;
      num -= (1LL << i);
    }
  }
  dbg(num);
  assert(num == 0LL);
  return 10201 * k + 101 * x + y;
}

void solve(int n) {
  int a, b; cin >> a >> b;
  ll d; cin >> d;

  vector<vector<bool>>obs(101,vector<bool>(101,false));
  
  vector<pair<int,int>>xy(n); for (int i=0; i<n; i++) cin >> xy[i].first >> xy[i].second;

  for (int i=0; i<n; i++) obs[xy[i].first][xy[i].second] = true;
  dbg(obs);

  // dp[i][d][x][y] := (x,y)で方向dを向いているときに2^i回移動したらいる場所 ([0,100] * [0,100]の外にいるならINTINF, そうでないなら 10201 * d + x * 101 + y

  auto dp = vector(60, vector(4, vector(101, vector(101, -1))));

  // i=0パターン
  for (int k=0; k<4; k++) {
    for (int x=0; x<=100; x++) {
      for (int y=0; y<=100; y++) {
        if (obs[x][y]) continue;

        int nx = x + dx[k];
        int ny = y + dy[k];
        
        // (nx,ny)が何もない[0,100]*[0,100]
        if (isin(nx,ny) && !obs[nx][ny]) {
          dp[0][k][x][y] = 10201 * k + nx * 101 + ny;
        }
        // (nx,ny)が障害物のある[0,100]*[0,100]
        else if (isin(nx,ny) && obs[nx][ny]) {
          int nx1 = x + dx[(k+1)%4];
          int nx2 = x + dx[(k+2)%4];
          int nx3 = x + dx[(k+3)%4];
          
          int ny1 = y + dy[(k+1)%4];
          int ny2 = y + dy[(k+2)%4];
          int ny3 = y + dy[(k+3)%4];

          if (isin(nx1,ny1) && !obs[nx1][ny1]) dp[0][k][x][y] = 10201 * ((k+1)%4) + nx1 * 101 + ny1;
          else if(!isin(nx1,ny1)) dp[0][k][x][y] = INTINF + (k+1)%4;

          else if (isin(nx2,ny2) && !obs[nx2][ny2]) dp[0][k][x][y] = 10201 * ((k+2)%4) + nx2 * 101 + ny2;
          else if(!isin(nx2,ny2)) dp[0][k][x][y] = INTINF + (k+2)%4;

          else if (isin(nx3,ny3) && !obs[nx3][ny3]) dp[0][k][x][y] = 10201 * ((k+3)%4) + nx3 * 101 + ny3;
          else if(!isin(nx3,ny3)) dp[0][k][x][y] = INTINF + (k+3)%4;

          // 袋小路やん
          else {
            dp[0][k][x][y] = -1;
          }
          
        }
        // (nx,ny)が何もない nx < 0 || 100 < nx || ny < 0 || 100 < ny 
        else if (nx < 0 || 100 < nx || ny < 0 || 100 < ny) {
          assert(!isin(nx,ny));
          dp[0][k][x][y] = INTINF + k;
        }
        else {
          dbg(k);
          dbg(x);
          dbg(y);
          dbg(nx);
          dbg(ny);
          assert(false);
        }
      }
    }
  }

  // dp[i][d][x][y] := (x,y)で方向dを向いているときに2^i回移動したらいる場所 ([0,100] * [0,100]の外にいるならINTINF, そうでないなら 10201 * d + x * 101 + y
  for (int i=0; i+1<60; i++) for (int k=0; k<4; k++) for (int x=0; x<=100; x++) for (int y=0; y<=100; y++) {
    if (obs[x][y]) continue;
    if (dp[i][k][x][y] == -1) continue;
    int nxt_val = dp[i][k][x][y];
    if (nxt_val >= INTINF) {
      dp[i+1][k][x][y] = nxt_val;
      continue;
    }
    int nxt_k = nxt_val / 10201;
    int nxt_x = nxt_val % 10201 / 101;
    int nxt_y = nxt_val % 10201 % 101;

    dp[i+1][k][x][y] = dp[i][nxt_k][nxt_x][nxt_y];
  }


  ll ok = 0;
  // ここ
  if (moove(dp,a,b,0,d) < INTINF) {
    int val = moove(dp,a,b,0,d);
    cout << val % 10201 / 101 << ' ' << val % 10201 % 101 << endl;
    return;
  }
  ll ng = d;

  while (abs(ng - ok) > 1) {
    ll mid = (ok + ng) / 2;
    if (moove(dp,a,b,0,mid) < INTINF) ok = mid;
    else ng = mid;
  }

  int val0 = moove(dp,a,b,0,ok);
  assert(val0 < INTINF);
  int k = val0 / 10201;
  ll x = val0 % 10201 / 101;
  ll y = val0 % 10201 % 101;

  if (!isin(x+dx[k], y+dy[k])) cout << x + ll(dx[k]) * (d-ok) << ' ' << y + ll(dy[k]) * (d-ok) << endl;
  else {
    k++;
    k %= 4;
    if (!isin(x+dx[k], y+dy[k])) cout << x + ll(dx[k]) * (d-ok) << ' ' << y + ll(dy[k]) * (d-ok) << endl;
    else {
      k++;
      k %= 4;
      if (!isin(x+dx[k], y+dy[k])) cout << x + ll(dx[k]) * (d-ok) << ' ' << y + ll(dy[k]) * (d-ok) << endl;
      else {
        k++;
        k %= 4;
        if (!isin(x+dx[k], y+dy[k])) cout << x + ll(dx[k]) * (d-ok) << ' ' << y + ll(dy[k]) * (d-ok) << endl;
        else assert(false);
      }
    }
  }
}

int main() {
  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  while (true) {
    int n; cin >> n;
    if (n == 0) return 0;
    solve(n);
  }
  return 0;
}
accuracy: 1
time_ms: 1400
memory_kb: 14080
final_rank: 17

code_snippet: #line 1 "D.cpp"
#include <iostream>
#include <utility>
#include <vector>
#include <cassert>
using namespace std;
using ll = long long;
template<class T> inline bool chmax(T& a, const T& b) {if (a<b) {a=b; return true;} return false;}
template<class T> inline bool chmin(T& a, const T& b) {if (b<a) {a=b; return true;} return false;}
constexpr int INTINF = 1000001000;
constexpr int INTMAX = 2147483647;
constexpr ll LLMAX = 9223372036854775807;
constexpr ll LLINF = 4450000000011100000;

#line 1 "/home/harui/CompetitiveProgramming/library/debug.hpp"



#ifdef LOCAL
#define dbg(x) std::cerr << __LINE__ << " : " << #x << " = " << (x) << std::endl
#else
#define dbg(x) true
#endif

#line 13 "/home/harui/CompetitiveProgramming/library/debug.hpp"
#include <set>


template <typename T, typename U>
std::ostream& operator<<(std::ostream& os, const std::pair<T, U>& p) {
  os << '(' << p.first << ", " << p.second << ')';
  return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {
  os << '[';
  for (int i=0; i<int(vec.size()); i++) {
    os << vec[i];
    if (i != int(vec.size())-1) os << ", ";
  }
  os << ']';
  return os;
}

template <typename T>
std::ostream& operator<<(std::ostream& os, const std::set<T>& st) {
  os << '{';
  auto itr = st.begin();
  while (itr != st.end()) {
    os << *itr;
    itr = next(itr);
    if (itr != st.end()) os << ", ";
  }
  os << '}';
  return os;
}



#line 15 "D.cpp"

const int dx[4] = {1,0,-1,0};
const int dy[4] = {0,1,0,-1};

bool isin(int x, int y) {
  return 0 <= x && x <= 100 && 0 <= y && y <= 100;
}

int moove (vector<vector<vector<vector<int>>>>const& dp, int x, int y, int k, ll num) {
  assert(isin(x,y));
  assert(0 <= k && k < 4);

  dbg(num);
  for (int i=0; i<60 && (1LL<<i)<=num && num > 0; i++) {
    if ((1LL << i) & num) {
      int nxt_val = dp[i][k][x][y];
      if (nxt_val >= INTINF) return nxt_val;
      int nxt_k = nxt_val / 10201;
      int nxt_x = nxt_val % 10201 / 101;
      int nxt_y = nxt_val % 10201 % 101;

      k = nxt_k;
      x = nxt_x;
      y = nxt_y;
      num -= (1LL << i);
    }
  }
  dbg(num);
  assert(num == 0LL);
  return 10201 * k + 101 * x + y;
}

void solve(int n) {
  int a, b; cin >> a >> b;
  ll d; cin >> d;

  vector<vector<bool>>obs(101,vector<bool>(101,false));
  
  vector<pair<int,int>>xy(n); for (int i=0; i<n; i++) cin >> xy[i].first >> xy[i].second;

  for (int i=0; i<n; i++) obs[xy[i].first][xy[i].second] = true;
  dbg(obs);

  // dp[i][d][x][y] := (x,y)で方向dを向いているときに2^i回移動したらいる場所 ([0,100] * [0,100]の外にいるならINTINF, そうでないなら 10201 * d + x * 101 + y

  auto dp = vector(60, vector(4, vector(101, vector(101, -1))));

  // i=0パターン
  for (int k=0; k<4; k++) {
    for (int x=0; x<=100; x++) {
      for (int y=0; y<=100; y++) {
        if (obs[x][y]) continue;

        int nx = x + dx[k];
        int ny = y + dy[k];
        
        // (nx,ny)が何もない[0,100]*[0,100]
        if (isin(nx,ny) && !obs[nx][ny]) {
          dp[0][k][x][y] = 10201 * k + nx * 101 + ny;
        }
        // (nx,ny)が障害物のある[0,100]*[0,100]
        else if (isin(nx,ny) && obs[nx][ny]) {
          int nx1 = x + dx[(k+1)%4];
          int nx2 = x + dx[(k+2)%4];
          int nx3 = x + dx[(k+3)%4];
          
          int ny1 = y + dy[(k+1)%4];
          int ny2 = y + dy[(k+2)%4];
          int ny3 = y + dy[(k+3)%4];

          if (isin(nx1,ny1) && !obs[nx1][ny1]) dp[0][k][x][y] = 10201 * ((k+1)%4) + nx1 * 101 + ny1;
          else if(!isin(nx1,ny1)) dp[0][k][x][y] = INTINF + (k+1)%4;

          else if (isin(nx2,ny2) && !obs[nx2][ny2]) dp[0][k][x][y] = 10201 * ((k+2)%4) + nx2 * 101 + ny2;
          else if(!isin(nx2,ny2)) dp[0][k][x][y] = INTINF + (k+2)%4;

          else if (isin(nx3,ny3) && !obs[nx3][ny3]) dp[0][k][x][y] = 10201 * ((k+3)%4) + nx3 * 101 + ny3;
          else if(!isin(nx3,ny3)) dp[0][k][x][y] = INTINF + (k+3)%4;

          // 袋小路やん
          else {
            dp[0][k][x][y] = -1;
          }
          
        }
        // (nx,ny)が何もない nx < 0 || 100 < nx || ny < 0 || 100 < ny 
        else if (nx < 0 || 100 < nx || ny < 0 || 100 < ny) {
          assert(!isin(nx,ny));
          dp[0][k][x][y] = INTINF + k;
        }
        else {
          dbg(k);
          dbg(x);
          dbg(y);
          dbg(nx);
          dbg(ny);
          assert(false);
        }
      }
    }
  }

  // dp[i][d][x][y] := (x,y)で方向dを向いているときに2^i回移動したらいる場所 ([0,100] * [0,100]の外にいるならINTINF, そうでないなら 10201 * d + x * 101 + y
  for (int i=0; i+1<60; i++) for (int k=0; k<4; k++) for (int x=0; x<=100; x++) for (int y=0; y<=100; y++) {
    if (obs[x][y]) continue;
    if (dp[i][k][x][y] == -1) continue;
    int nxt_val = dp[i][k][x][y];
    if (nxt_val >= INTINF) {
      dp[i+1][k][x][y] = nxt_val;
      continue;
    }
    int nxt_k = nxt_val / 10201;
    int nxt_x = nxt_val % 10201 / 101;
    int nxt_y = nxt_val % 10201 % 101;

    dp[i+1][k][x][y] = dp[i][nxt_k][nxt_x][nxt_y];
  }


  ll ok = 0;
  if (moove(dp,a,b,0,d) < INTINF) {
    int val = moove(dp,a,b,0,d);
    cout << val % 10201 / 101 << ' ' << val % 10201 % 101 << endl;
    return;
  }
  ll ng = d;

  while (abs(ng - ok) > 1) {
    ll mid = (ok + ng) / 2;
    if (moove(dp,a,b,0,mid) < INTINF) ok = mid;
    else ng = mid;
  }

  int val0 = moove(dp,a,b,0,ok);
  int val1 = moove(dp,a,b,0,ok+1);

  int k = val1 - INTINF;
  ll x = val0 % 10201 / 101 + dx[k];
  ll y = val0 % 10201 % 101 + dy[k];
	// cerr << x <<" " <<  y << endl;
  cout << x + ll(dx[k]) * (d - ok-1) << ' ' << y + ll(dy[k]) * (d - ok-1)<< endl;
}

int main() {
  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  while (true) {
    int n; cin >> n;
    if (n == 0) return 0;
    solve(n);
  }
  return 0;
}
accuracy: 1
time_ms: 1390
memory_kb: 14080
final_rank: 16

code_snippet: //AC
#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
#define int long long

void solve(int n) {
    int direct = 1;
    int a, b, d;
    cin >> a >> b >> d;
    map<int, vector<int>> keyx, keyy;
    set<int> sx, sy;
    for (int i=0; i<n; ++i) {
        int x, y;
        cin >> x >> y;
        sx.insert(x);
        sy.insert(y);
        keyx[x].push_back(y);
        keyy[y].push_back(x);
    }

    for (auto x_: sx) {
        sort(keyx[x_].begin(), keyx[x_].end());
    }
    for (auto y_: sy) {
        sort(keyy[y_].begin(), keyy[y_].end());
    }

    map<tuple<int, int, int>, int> last_step;
    map<tuple<int, int, int>, int> existed;

    // for (int _=0; _<10; ++_) cout << "=";
    // cout << "here~~" << "\n";

    int cnt = 0;
    while (d > 0) {
        if (existed[{a, b, direct}] == 1) {
            int len_cycle = last_step[{a, b, direct}] - d;
            d %= len_cycle;
            // cout << "len cycle = " << len_cycle << endl;
            // cout << "changed d = " << d << endl;
        }
        // cout << a << ' ' << b << ' ' << d << " dir = " << direct << endl;

        last_step[{a, b, direct}] = d;
        existed[{a, b, direct}]++;
        if (direct == 1) {
            //right
            //(a, b)にいるからkeyy[b]の配列でaよりも右にある最初の座標を取得する
            
            auto itr = upper_bound(keyy[b].begin(), keyy[b].end(), a);
            if (itr == keyy[b].end()) {
                //全部使い切る
                a += d;
                d = 0;
            } else {
                if (a + d < *itr) {
                    //全部使い切る
                    a += d;
                    d = 0;
                } else {
                    int can = *itr - a - 1;
                    a += can;
                    d -= can;
                }
            }
        } else if (direct == 0) {
            //up
            auto itr = upper_bound(keyx[a].begin(), keyx[a].end(), b);
            if (itr == keyx[a].end()) {
                //全部使い切る
                b += d;
                d = 0;
            } else {
                if (b + d < *itr) {
                    //全部使い切る
                    b += d;
                    d = 0;
                } else {
                    int can = *itr - b - 1;
                    b += can;
                    d -= can;
                }
            }
        } else if (direct == 3) {
            //left
            auto itr = lower_bound(keyy[b].begin(), keyy[b].end(), a);
            if (itr == keyy[b].begin()) {
                //全部使い切る
                a -= d;
                d = 0;
            } else {
                --itr;
                if (a - d > *itr) {
                    //全部使い切る
                    a -= d;
                    d = 0;
                } else {
                    int can = a - *itr- 1;
                    a -= can;
                    d -= can;
                }
            }
        } else {
            //down
            auto itr = lower_bound(keyx[a].begin(), keyx[a].end(), b);
            if (itr == keyx[a].begin()) {
                //全部使い切る
                b -= d;
                d = 0;
            } else {
                --itr;
                if (b - d > *itr) {
                    //全部使い切る
                    b -= d;
                    d = 0;
                } else {
                    int can = b - *itr- 1;
                    b -= can;
                    d -= can;
                }
            }

        }
        direct += 3;
        direct %= 4;
    }
    cout << a << ' ' << b << endl;
}

signed main() {
    while(true) {
        int n;
        cin >> n;
        if (n == 0) break;
        solve(n);
    }
}

/*
memo


2
0 1 4
3 1
2 5

2
0 1 9
3 1
2 5

12
2 2 11
0 1
0 2
0 3
4 1
4 2
4 3
3 4
2 4
1 4
3 0
2 0
1 0

12
2 2 7791772263873
0 1
0 2
0 3
4 1
4 2
4 3
3 4
2 4
1 4
3 0
2 0
1 0

3
0 3 198
99 2
100 3
99 4

3
0 3 1000000000000000000
99 2
100 3
99 4

1
99 100 1
100 100
0

*/
accuracy: 1
time_ms: 20
memory_kb: 3712
final_rank: 5

code_snippet: #include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
#define int long long

void solve(int n) {
    int direct = 1;
    int a, b, d;
    cin >> a >> b >> d;
    map<int, vector<int>> keyx, keyy;
    set<int> sx, sy;
    for (int i=0; i<n; ++i) {
        int x, y;
        cin >> x >> y;
        sx.insert(x);
        sy.insert(y);
        keyx[x].push_back(y);
        keyy[y].push_back(x);
    }

    for (auto x_: sx) {
        sort(keyx[x_].begin(), keyx[x_].end());
    }
    for (auto y_: sy) {
        sort(keyy[y_].begin(), keyy[y_].end());
    }

    map<tuple<int, int, int>, int> last_step;
    map<tuple<int, int, int>, int> existed;

    // for (int _=0; _<10; ++_) cout << "=";
    // cout << "here~~" << "\n";

    int cnt = 0;
    while (d > 0) {
        if (existed[{a, b, direct}] == 1) {
            int len_cycle = last_step[{a, b, direct}] - d;
            d %= len_cycle;
            // cout << "len cycle = " << len_cycle << endl;
            // cout << "changed d = " << d << endl;
        }
        // cout << a << ' ' << b << ' ' << d << " dir = " << direct << endl;

        last_step[{a, b, direct}] = d;
        existed[{a, b, direct}]++;
        if (direct == 1) {
            //right
            //(a, b)にいるからkeyy[b]の配列でaよりも右にある最初の座標を取得する
            
            auto itr = upper_bound(keyy[b].begin(), keyy[b].end(), a);
            if (itr == keyy[b].end()) {
                //全部使い切る
                a += d;
                d = 0;
            } else {
                if (a + d < *itr) {
                    //全部使い切る
                    a += d;
                    d = 0;
                } else {
                    int can = *itr - a - 1;
                    a += can;
                    d -= can;
                }
            }
        } else if (direct == 0) {
            //up
            auto itr = upper_bound(keyx[a].begin(), keyx[a].end(), b);
            if (itr == keyx[a].end()) {
                //全部使い切る
                b += d;
                d = 0;
            } else {
                if (b + d < *itr) {
                    //全部使い切る
                    b += d;
                    d = 0;
                } else {
                    int can = *itr - b - 1;
                    b += can;
                    d -= can;
                }
            }
        } else if (direct == 3) {
            //left
            auto itr = lower_bound(keyy[b].begin(), keyy[b].end(), a);
            if (itr == keyy[b].begin()) {
                //全部使い切る
                a -= d;
                d = 0;
            } else {
                --itr;
                if (a - d > *itr) {
                    //全部使い切る
                    a -= d;
                    d = 0;
                } else {
                    int can = a - *itr- 1;
                    a -= can;
                    d -= can;
                }
            }
        } else {
            //down
            auto itr = lower_bound(keyx[a].begin(), keyx[a].end(), b);
            if (itr == keyx[a].begin()) {
                //全部使い切る
                b -= d;
                d = 0;
            } else {
                --itr;
                if (b - d > *itr) {
                    //全部使い切る
                    b -= d;
                    d = 0;
                } else {
                    int can = b - *itr- 1;
                    b -= can;
                    d -= can;
                }
            }

        }
        direct += 3;
        direct %= 4;
    }
    cout << a << ' ' << b << endl;

}

signed main() {
    while(true) {
        int n;
        cin >> n;
        if (n == 0) break;
        solve(n);
    }
}

/*
memo


2
0 1 4
3 1
2 5

2
0 1 9
3 1
2 5

12
2 2 11
0 1
0 2
0 3
4 1
4 2
4 3
3 4
2 4
1 4
3 0
2 0
1 0

12
2 2 7791772263873
0 1
0 2
0 3
4 1
4 2
4 3
3 4
2 4
1 4
3 0
2 0
1 0

3
0 3 198
99 2
100 3
99 4

3
0 3 1000000000000000000
99 2
100 3
99 4

1
99 100 1
100 100
0

*/
accuracy: 1
time_ms: 20
memory_kb: 3712
final_rank: 5

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

typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<ll>> vvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
inline ll lfloor(ll x,ll m){return (x - ((x % m+ m)%m))/m;}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {1,0,-1,0,1,1,-1,-1};//x
vector<ll> _yo = {0,1,0,-1,1,-1,1,-1};//y
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
	
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

void solve(ll n){
	LL(a,b,d);
	vpll xy(n);
	rep(i,n){
		cin >> xy[i].first >> xy[i].second;
	}	
	vvll obj(101,vll(101));
	rep(i,n){
		auto [x,y] = xy[i];
		obj[x][y]++;
	}
	vector dp(61,vector(101,vector(101,vector<tpl3>(4,{INF,INF,INF}))));

	rep(i,101)rep(j,101)if(obj[i][j]== 0){
		rep(k,4){
			ll ny = i +_ta[k];
			ll nx = j +_yo[k];
			if(!isin(ny,nx,101,101)){
				dp[0][i][j][k] = {INF,INF,k};
				continue;
			}
			if(obj[ny][nx] == 0){
				dp[0][i][j][k] = {ny,nx,k};
				continue;
			}
			ll nk =(k+1)%4;
			bool fin = false;
			while(nk != k){
				ny = i +_ta[nk];
				nx = j +_yo[nk];
				if(!isin(ny,nx,101,101)){
					dp[0][i][j][k] = {INF,INF,nk};
					fin = true;
					break;
				}
				if(obj[ny][nx] == 0){
					dp[0][i][j][k] = {ny,nx,nk};
					fin = true;
					break;
				}
				nk++;
				nk %= 4;
			}
			if(!fin){
				dp[0][i][j][k] = {i,j,k};
			}

		}
	}
	rep(z,60){
		rep(i,101)rep(j,101)rep(k,4){
			auto [pi,pj,pk] = dp[z][i][j][k];
			if(pi == INF)continue;
			dp[z+1][i][j][k] = dp[z][pi][pj][pk];
		}
	}
	{
		ll i = a,j = b;
		ll k = 0;
		rep(z,60){
			if(d >> z & 1){
				auto [ni,nj,nk] = dp[z][i][j][k];
				i = ni;
				j = nj;
				k = nk;
				if(i == INF )break;
			}
		}
		if(i != INF){
			cout << i << " " << j << endl; 
			return ;
		}
	}
	ll ng = d;//条件を満たさない値
	ll ok = 0;//条件を満たす値
	auto f = [&](ll mid)->bool{
		ll i = a,j = b;
		ll k = 0;
		rep(z,60){
			if(mid>> z & 1){
				auto [ni,nj,nk] = dp[z][i][j][k];
				i = ni;
				j = nj;
				k = nk;
				if(i == INF )break;
			}
		}
		return i != INF;
	};
	while(abs(ok-ng) > 1){
		ll mid = (ok + ng)/2;
		if(f(mid)){
			ok = mid;
		}else{
			ng = mid;
		}
	}
	//ok回までは行ける
	ll i = a,j = b;
	ll k = 0;
	rep(z,60){
		if(ok >> z & 1){
			auto [ni,nj,nk] = dp[z][i][j][k];
			i = ni;
			j = nj;
			k = nk;
		}
	}
	ll rem = d- ok;
	 k = get<2>(dp[0][i][j][k]);
	cout << i + _ta[k]*rem << " " << j + _yo[k]*rem << endl;
}

int main(){
	ios::sync_with_stdio(false);cin.tie(nullptr);
	while(true){
		LL(n);
		if(n == 0)return 0;
		solve(n);
	}
}
accuracy: 1
time_ms: 6690
memory_kb: 87768
final_rank: 20