#include <bits/stdc++.h> using namespace std; using ll=long long; using Point=pair<ll, ll>; #define x first #define y second inline Point operator +(Point a, Point b) { return Point(a.x+b.x, a.y+b.y); } inline Point rotate_point(Point a, int rot) // > -> ^ -> < -> v { if(rot==0) return a; return rotate_point(Point(-a.y, a.x), rot-1); } inline Point abs_y(Point a) { return Point(a.x, abs(a.y)); } inline Point abs_x(Point a) { return Point(abs(a.x), a.y); } inline Point neg_abs_y(Point a) { return Point(a.x, -abs(a.y)); } inline Point neg_abs_x(Point a) { return Point(-abs(a.x), a.y); } inline void print_point(Point a) { printf("%lld %lld\n", a.x, a.y); } const int RIGHT=0, UP=1, LEFT=2, DOWN=3, N=31; const int recur[4][2][2]= { {{DOWN, RIGHT}, {UP, RIGHT}}, {{UP, UP}, {RIGHT, LEFT}}, {{LEFT, DOWN}, {LEFT, UP}}, {{RIGHT, LEFT}, {DOWN, DOWN}} }; ll bt[N][4][4]= {{}, { {6, 2, 2, 2}, {6, 2, 2, 2}, {6, 2, 2, 2}, {6, 2, 2, 2} }}; ll bt_down[N]={0, 0}, bt_up[N]={0, 4}; Point get_position_down(int, ll); Point get_position_up(int, ll); Point get_position(int n, ll t, int dir_l, int dir_r) //poczatek w (0, 1) { ll m=(1LL<<n); if(n==1) { if(t==0) return Point(0, 1); if(t==1) return Point(1, 2); if(dir_r==RIGHT) { if(t==2) return Point(2, 3); if(t==3) return Point(3, 2); if(t==4) return Point(2, 1); if(t==5) return Point(1, 2); } assert(0); //jezeli tu jestesmy, to stalo sie cos bardzo zlego } if(t<bt[n-1][recur[dir_l][1][1]][recur[dir_r][1][0]]) return get_position(n-1, t, recur[dir_l][1][1], recur[dir_r][1][0]); t-=bt[n-1][recur[dir_l][1][1]][recur[dir_r][1][0]]; if(t==0) return Point(0, m-1); --t; if(dir_l==RIGHT) { if(t<bt_down[n]) return rotate_point(get_position_down(n, t), 1)+Point(0, m); t-=bt_down[n]; } if(dir_l==LEFT) { if(t<bt_up[n]) return rotate_point(get_position_up(n, t), 1)+Point(0, m); t-=bt_up[n]; } if(t==0) return Point(-1, m); --t; assert(t<bt[n-1][recur[dir_l][0][1]][recur[dir_r][0][0]]); return get_position(n-1, t, recur[dir_l][0][1], recur[dir_r][0][0])+Point(0, m); } Point get_position_down(int n, ll t) { assert(n>1); ll m=(1LL<<n); if(t<bt[n-1][DOWN][DOWN]) return get_position(n-1, t, DOWN, DOWN); t-=bt[n-1][DOWN][DOWN]; return rotate_point(get_position(n-1, t, UP, UP), 2)+Point(0, m); } Point get_position_up(int n, ll t) { if(n==1) { if(t==0) return Point(0, 1); if(t==1) return Point(1, 2); if(t==2) return Point(0, 3); if(t==3) return Point(-1, 2); assert(0); //nie powinnismy tu byc } ll m=(1LL<<n); if(t<bt[n-1][RIGHT][LEFT]) return get_position(n-1, t, RIGHT, LEFT); t-=bt[n-1][RIGHT][LEFT]; if(t==0) return Point(0, m-1); --t; if(t<bt[n-1][DOWN][RIGHT]) return rotate_point(get_position(n-1, t, DOWN, RIGHT), 1)+Point(0, m); t-=bt[n-1][DOWN][RIGHT]; if(t<bt[n-1][LEFT][UP]) return rotate_point(get_position(n-1, t, LEFT, UP), 3)+Point(-m, m); t-=bt[n-1][LEFT][UP]; if(t==0) return Point(-1, m); --t; if(t==0) return Point(0, m+1); --t; if(t<bt[n-1][LEFT][DOWN]) return rotate_point(get_position(n-1, t, LEFT, DOWN), 3)+Point(0, m); t-=bt[n-1][LEFT][DOWN]; if(t<bt[n-1][UP][RIGHT]) return rotate_point(get_position(n-1, t, UP, RIGHT), 1)+Point(m, m); t-=bt[n-1][UP][RIGHT]; if(t==0) return Point(1, m); --t; return rotate_point(get_position(n-1, t, RIGHT, LEFT), 2)+Point(0, m); } Point get_real_position(int n, ll t) { ll m=(1LL<<n); if(t<bt[n][LEFT][RIGHT]) return abs_y(rotate_point(get_position(n, t, LEFT, RIGHT), 3)); t-=bt[n][LEFT][RIGHT]; if(t==0) return Point(2*m-1, 0); --t; if(t<bt[n][UP][UP]) return neg_abs_x(get_position(n, t, UP, UP))+Point(2*m, 0); t-=bt[n][UP][UP]; if(t==0) return Point(2*m, 2*m-1); --t; if(t<bt[n][RIGHT][LEFT]) return neg_abs_y(rotate_point(get_position(n, t, RIGHT, LEFT), 1))+Point(2*m, 2*m); t-=bt[n][RIGHT][LEFT]; if(t==0) return Point(1, 2*m); --t; if(t<bt[n][DOWN][DOWN]) return abs_x(rotate_point(get_position(n, t, DOWN, DOWN), 2))+Point(0, 2*m); t-=bt[n][DOWN][DOWN]; assert(t==0); return Point(1, 0); } int main() { int n; scanf("%d", &n); for(int i=2; i<=n; ++i) { bt_down[i]=bt[i-1][DOWN][DOWN]+bt[i-1][UP][UP]; bt_up[i]=bt[i-1][RIGHT][LEFT]+1+bt[i-1][DOWN][RIGHT]+bt[i-1][LEFT][UP]+2+bt[i-1][LEFT][DOWN]+bt[i-1][UP][RIGHT]+1+bt[i-1][RIGHT][LEFT]; for(int k=0; k<4; ++k) for(int l=0; l<4; ++l) { bt[i][k][l]=bt[i-1][recur[k][1][1]][recur[l][1][0]]+2+bt[i-1][recur[k][0][1]][recur[l][0][0]]; if(k==RIGHT) bt[i][k][l]+=bt_down[i]; if(k==LEFT) bt[i][k][l]+=bt_up[i]; } } int z; scanf("%d", &z); while(z--) { ll t; scanf("%lld", &t); print_point(get_real_position(n, t)); } //for(int i=0; i<(1<<(2*(n+1))); ++i) print_point(get_real_position(n, i)); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | #include <bits/stdc++.h> using namespace std; using ll=long long; using Point=pair<ll, ll>; #define x first #define y second inline Point operator +(Point a, Point b) { return Point(a.x+b.x, a.y+b.y); } inline Point rotate_point(Point a, int rot) // > -> ^ -> < -> v { if(rot==0) return a; return rotate_point(Point(-a.y, a.x), rot-1); } inline Point abs_y(Point a) { return Point(a.x, abs(a.y)); } inline Point abs_x(Point a) { return Point(abs(a.x), a.y); } inline Point neg_abs_y(Point a) { return Point(a.x, -abs(a.y)); } inline Point neg_abs_x(Point a) { return Point(-abs(a.x), a.y); } inline void print_point(Point a) { printf("%lld %lld\n", a.x, a.y); } const int RIGHT=0, UP=1, LEFT=2, DOWN=3, N=31; const int recur[4][2][2]= { {{DOWN, RIGHT}, {UP, RIGHT}}, {{UP, UP}, {RIGHT, LEFT}}, {{LEFT, DOWN}, {LEFT, UP}}, {{RIGHT, LEFT}, {DOWN, DOWN}} }; ll bt[N][4][4]= {{}, { {6, 2, 2, 2}, {6, 2, 2, 2}, {6, 2, 2, 2}, {6, 2, 2, 2} }}; ll bt_down[N]={0, 0}, bt_up[N]={0, 4}; Point get_position_down(int, ll); Point get_position_up(int, ll); Point get_position(int n, ll t, int dir_l, int dir_r) //poczatek w (0, 1) { ll m=(1LL<<n); if(n==1) { if(t==0) return Point(0, 1); if(t==1) return Point(1, 2); if(dir_r==RIGHT) { if(t==2) return Point(2, 3); if(t==3) return Point(3, 2); if(t==4) return Point(2, 1); if(t==5) return Point(1, 2); } assert(0); //jezeli tu jestesmy, to stalo sie cos bardzo zlego } if(t<bt[n-1][recur[dir_l][1][1]][recur[dir_r][1][0]]) return get_position(n-1, t, recur[dir_l][1][1], recur[dir_r][1][0]); t-=bt[n-1][recur[dir_l][1][1]][recur[dir_r][1][0]]; if(t==0) return Point(0, m-1); --t; if(dir_l==RIGHT) { if(t<bt_down[n]) return rotate_point(get_position_down(n, t), 1)+Point(0, m); t-=bt_down[n]; } if(dir_l==LEFT) { if(t<bt_up[n]) return rotate_point(get_position_up(n, t), 1)+Point(0, m); t-=bt_up[n]; } if(t==0) return Point(-1, m); --t; assert(t<bt[n-1][recur[dir_l][0][1]][recur[dir_r][0][0]]); return get_position(n-1, t, recur[dir_l][0][1], recur[dir_r][0][0])+Point(0, m); } Point get_position_down(int n, ll t) { assert(n>1); ll m=(1LL<<n); if(t<bt[n-1][DOWN][DOWN]) return get_position(n-1, t, DOWN, DOWN); t-=bt[n-1][DOWN][DOWN]; return rotate_point(get_position(n-1, t, UP, UP), 2)+Point(0, m); } Point get_position_up(int n, ll t) { if(n==1) { if(t==0) return Point(0, 1); if(t==1) return Point(1, 2); if(t==2) return Point(0, 3); if(t==3) return Point(-1, 2); assert(0); //nie powinnismy tu byc } ll m=(1LL<<n); if(t<bt[n-1][RIGHT][LEFT]) return get_position(n-1, t, RIGHT, LEFT); t-=bt[n-1][RIGHT][LEFT]; if(t==0) return Point(0, m-1); --t; if(t<bt[n-1][DOWN][RIGHT]) return rotate_point(get_position(n-1, t, DOWN, RIGHT), 1)+Point(0, m); t-=bt[n-1][DOWN][RIGHT]; if(t<bt[n-1][LEFT][UP]) return rotate_point(get_position(n-1, t, LEFT, UP), 3)+Point(-m, m); t-=bt[n-1][LEFT][UP]; if(t==0) return Point(-1, m); --t; if(t==0) return Point(0, m+1); --t; if(t<bt[n-1][LEFT][DOWN]) return rotate_point(get_position(n-1, t, LEFT, DOWN), 3)+Point(0, m); t-=bt[n-1][LEFT][DOWN]; if(t<bt[n-1][UP][RIGHT]) return rotate_point(get_position(n-1, t, UP, RIGHT), 1)+Point(m, m); t-=bt[n-1][UP][RIGHT]; if(t==0) return Point(1, m); --t; return rotate_point(get_position(n-1, t, RIGHT, LEFT), 2)+Point(0, m); } Point get_real_position(int n, ll t) { ll m=(1LL<<n); if(t<bt[n][LEFT][RIGHT]) return abs_y(rotate_point(get_position(n, t, LEFT, RIGHT), 3)); t-=bt[n][LEFT][RIGHT]; if(t==0) return Point(2*m-1, 0); --t; if(t<bt[n][UP][UP]) return neg_abs_x(get_position(n, t, UP, UP))+Point(2*m, 0); t-=bt[n][UP][UP]; if(t==0) return Point(2*m, 2*m-1); --t; if(t<bt[n][RIGHT][LEFT]) return neg_abs_y(rotate_point(get_position(n, t, RIGHT, LEFT), 1))+Point(2*m, 2*m); t-=bt[n][RIGHT][LEFT]; if(t==0) return Point(1, 2*m); --t; if(t<bt[n][DOWN][DOWN]) return abs_x(rotate_point(get_position(n, t, DOWN, DOWN), 2))+Point(0, 2*m); t-=bt[n][DOWN][DOWN]; assert(t==0); return Point(1, 0); } int main() { int n; scanf("%d", &n); for(int i=2; i<=n; ++i) { bt_down[i]=bt[i-1][DOWN][DOWN]+bt[i-1][UP][UP]; bt_up[i]=bt[i-1][RIGHT][LEFT]+1+bt[i-1][DOWN][RIGHT]+bt[i-1][LEFT][UP]+2+bt[i-1][LEFT][DOWN]+bt[i-1][UP][RIGHT]+1+bt[i-1][RIGHT][LEFT]; for(int k=0; k<4; ++k) for(int l=0; l<4; ++l) { bt[i][k][l]=bt[i-1][recur[k][1][1]][recur[l][1][0]]+2+bt[i-1][recur[k][0][1]][recur[l][0][0]]; if(k==RIGHT) bt[i][k][l]+=bt_down[i]; if(k==LEFT) bt[i][k][l]+=bt_up[i]; } } int z; scanf("%d", &z); while(z--) { ll t; scanf("%lld", &t); print_point(get_real_position(n, t)); } //for(int i=0; i<(1<<(2*(n+1))); ++i) print_point(get_real_position(n, i)); } |