#include // #if __has_include() // # include // #endif // using namespace atcoder; // 定義系 namespace Define { // 引数に応じて呼び出しを変える,for文 #define rep_overload(e1, e2, e3, e4, NAME, ...) NAME #define REP_OVERLOAD(e1, e2, e3, e4, NAME, ...) NAME #define rrep_overload(e1, e2, e3, e4, NAME, ...) NAME #define RREP_OVERLOAD(e1, e2, e3, e4, NAME, ...) NAME // for文 #define rep1(i, lim) for (int i = (int)0; i < (int)lim; i++) #define rep2(i, x, lim) for (int i = (int)x; i < (int)lim; i++) #define rep3(i, x, lim, gap) for (int i = (int)x; i < (int)lim; i += gap) #define rep(i, ...) rep_overload(i, __VA_ARGS__, rep3, rep2, rep1)(i, __VA_ARGS__) #define REP1(i, lim) for (int i = (int)0; i <= (int)lim; i++) #define REP2(i, x, lim) for (int i = (int)x; i <= (int)lim; i++) #define REP3(i, x, lim, gap) for (int i = (int)x; i <= (int)lim; i += (int)gap) #define REP(i, ...) REP_OVERLOAD(i, __VA_ARGS__, REP3, REP2, REP1)(i, __VA_ARGS__) #define rrep1(i, x) for (int i = (int)x; i > 0; i--) #define rrep2(i, x, lim) for (int i = (int)x; i > (int)lim; i--) #define rrep3(i, x, lim, gap) for (int i = (int)x; i > (int)lim; i -= gap) #define rrep(i, ...) rrep_overload(i, __VA_ARGS__, rrep3, rrep2, rrep1)(i, __VA_ARGS__) #define RREP1(i, x) for (int i = (int)x; i >= 0; i--) #define RREP2(i, x, lim) for (int i = (int)x; i >= (int)lim; i--) #define RREP3(i, x, lim, gap) for (int i = (int)x; i >= (int)lim; i -= (int)gap) #define RREP(i, ...) RREP_OVERLOAD(i, __VA_ARGS__, RREP3, RREP2, RREP1)(i, __VA_ARGS__) #define all(x) x.begin(), x.end() #define rall(x) x.rbegin(), x.rend() #define el "\n" #define spa " " #define eps (1e-10) #define Equals(a, b) (fabs((a) - (b)) < eps) } // namespace Define // 拡張メソッド的なもの namespace Extensions { template> class vector : public std::vector { using std::vector::vector; public: std::string Join(std::string sep = "") { std::ostringstream oss; if (!this->empty()) { oss << this->at(0); rep(i, 1, this->size()) oss << sep << this->at(i); } return oss.str(); } }; // vector型判定 template struct is_vec : std::false_type {}; template struct is_vec> : std::true_type {}; template constexpr bool is_vector = is_vec::value; template constexpr bool is_num = std::is_integral_v || std::is_floating_point_v; } // namespace Extensions // いろいろ namespace Contest { using std::pair, std::string, std::set, std::map; using namespace Extensions; // clang-format off using ll = long long; using pii = pair; using pll = pair; using pss = pair; using vpii = vector; using vpll = vector; using vpss = vector; using psl = pair; using pls = pair; using vpsl = vector; using vpls = vector; using vi = vector; using vvi = vector; using vl = vector; using vvl = vector; using vb = vector; using vvb = vector; using vc = vector; using vvc = vector; using vd = vector; using vvd = vector; using vs = vector; using vvs = vector; // clang-format on const double PI = acos(-1); const int DX[4] = { 1, 0, -1, 0 }; // (下,右,上,左) const int DY[4] = { 0, 1, 0, -1 }; const int INF = 1001001001; const ll INFL = 4004004003094073385LL; // (int)INFL = INF, (int)(-INFL) = -INF; const string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const string abc = "abcdefghijklmnopqrstuvwxyz"; // 大きい値を第一引数に上書き template inline bool chmax(T1 &a, T2 b) { bool compare = a < b; if (compare) a = b; return compare; } // 小さい値を第一引数に上書き template inline bool chmin(T1 &a, T2 b) { bool compare = a > b; if (compare) a = b; return compare; } // 文字列区切り static vector Split(const string &s, char delim = ' ') { vector elems; string item; for (char ch : s) { if (ch == delim) { if (!item.empty()) elems.push_back(item); item.clear(); } else item += ch; } if (!item.empty()) elems.push_back(item); return elems; } // index取得 template ll IndexOf(vector vt, T target) { return std::distance(vt.begin(), std::find(all(vt), target)); } // 最小値取得 template T Min(vector vt) { return *std::min_element(all(vt)); } // 最大値取得 template T Max(vector vt) { return *std::max_element(all(vt)); } } // namespace Contest // 入出力 namespace IO { using namespace Contest; class Scanner { private: int _int; vector _str; public: Scanner() { _int = 0; _str.clear(); } string Next() { if (_int < (int)_str.size()) return _str[_int++]; string st; getline(std::cin, st); while (st == "") getline(std::cin, st); _str = Contest::Split(st); if (_str.size() == 0) return Next(); _int = 0; return _str[_int++]; } string NextLine() { if (_int < (int)_str.size()) { vector vec(_str.size() - _int); std::copy(_str.begin() + _int, _str.end(), vec.begin()); auto s = " " + vec.Join(" "); _str.clear(); return s; } string st; getline(std::cin, st); while (st == "") getline(std::cin, st); _str.clear(); _str.emplace_back(st); _int = 0; return _str[_int++]; } int NextInt() { return std::stoi(Next()); } ll NextLL() { return std::stoll(Next()); } double NextDouble() { return std::stod(Next()); } }; auto sc = new Scanner(); struct FastIO { FastIO() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); std::cout << std::fixed << std::setprecision(18); } } FastIOtmp; ll InputNum() { return sc->NextLL(); } pll InputNumPair() { pll p(InputNum(), InputNum()); return p; } vpll InputsNumPair(ll n) { vpll vec; rep(i, n) vec.emplace_back(InputNumPair()); return vec; } vl InputNums(ll n) { vl vec; rep(i, n) vec.emplace_back(InputNum()); return vec; } vvl InputsNums(ll h, ll w) { vvl vec; rep(i, h) vec.emplace_back(InputNums(w)); return vec; } string InputString() { return sc->Next(); } string InputStringLine() { return sc->NextLine(); } vs InputStrings(ll n) { vs vec; rep(i, n) vec.emplace_back(InputString()); return vec; } vs InputStringLines(ll n) { vs vec; rep(i, n) vec.emplace_back(InputStringLine()); return vec; } vvs InputsStrings(ll h, ll w) { vvs vec; rep(i, h) vec.emplace_back(InputStrings(w)); return vec; } template void Output(T n, string end = el) { std::cout << n << end; } void Output(bool n, string t = "Yes", string f = "No") { std::cout << (n ? t : f) << el; } void Output(double n, string end = el) { std::cout << n << end; } void Output(string n, string end = el) { std::cout << n << end; } void Output(const char *n) { Output(string(n)); } void Output(vs n, string sep = " ", string end = el) { Output(n.Join(sep), end); } void Output(vvs n, string sep = " ", string end = el) { rep(i, n.size()) Output(n[i].Join(sep), end); } void Output(ll n, string end = el) { std::cout << n << end; } void Output(pll n, string sep = " ", string end = el) { std::cout << n.first << sep << n.second << end; } void Output(vpll n, string sep = " ", string end = el) { rep(i, n.size()) Output(n[i], sep, end); } void Output(vl n, string sep = " ") { Output(n.Join(sep)); } void Output(vvl n, string sep = " ", string end = el) { rep(i, n.size()) Output(n[i].Join(sep), end); } } // namespace IO void Solve() { using namespace std; using namespace IO; auto N = InputNum(); auto M = InputNum(); vpll ans; ans.emplace_back(N * M, N * M); rep(i, N) { ans.emplace_back(i + 1, (i + 1) % N + 1); } ll margin = 0; ll to = 0; REP(i, 1, N) { rep(j, M - 1) { if (j == 0) { to = i + N + margin; ans.emplace_back(i, to); } else { ans.emplace_back(to, to + 1); to++; } } margin += M - 2; } Output(ans); } int main() { Solve(); return 0; }