using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Numerics; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using static System.Console; using static System.Math; using static Contest.PrimeNumber; namespace Contest { internal class Program { private static void Solve() { var N = InputNum().ToInt(); var M = InputNum().ToInt(); var ans = new List>(); ans.Add(new List() { N * M, N * M }); for (var i = 1; i <= N; i++) { if (i != N) ans.Add(new List() { i, i + 1 }); else ans.Add(new List() { 1, N }); } var margin = 0; var from = 0; var to = 0; for (var i = 1; i <= N; i++) { for (var j = 0; j < M - 1; j++) { if (j == 0) { from = i; to = i + N + margin; ans.Add(new List() { from, to }); } else { ans.Add(new List() { to, to + 1 }); to++; } } margin += M - 2; } for (var i = 0; i < ans.Count; i++) Output(ans[i]); } static void Main(string[] args) { var sw = new StreamWriter(OpenStandardOutput()) { AutoFlush = false }; SetOut(sw); Solve(); Out.Flush(); } static readonly Scanner sc = new Scanner(); static long InputNum() { return sc.NextLong(); } static List InputNums(long n) { var li = new List(); for (var i = 0; i < n; i++) li.Add(InputNum()); return li; } static List> InputsNums(long h, long w) { var li = new List>(); for (var i = 0; i < h; i++) li.Add(InputNums(w)); return li; } static string InputString() { return sc.Next(); } static string InputStringLine() { return sc.NextLine(); } static List InputStrings(long n) { var li = new List(); for (var i = 0; i < n; i++) li.Add(InputString()); return li; } static List InputStringLines(long n) { var li = new List(); for (var i = 0; i < n; i++) li.Add(InputStringLine()); return li; } static List> InputsStrings(long h, long w) { var li = new List>(); for (var i = 0; i < h; i++) li.Add(InputStrings(w)); return li; } static void Output(object n) => WriteLine(n.ToString()); static void Output(string n) => WriteLine(n); static void Output(bool n, string t = "Yes", string f = "No") => WriteLine(n ? t : f); static void Output(IEnumerable ts, string sep = " ") => WriteLine(string.Join(sep, ts)); } #region いろいろ public static class Methods { /// /// 型変換 /// #region ToNum public static int ToInt(this object target) { _ = int.TryParse(target.ToString(), out var val); return val; } public static long ToLong(this object target) { _ = long.TryParse(target.ToString(), out var val); return val; } public static byte ToByte(this object target) { _ = byte.TryParse(target.ToString(), out var val); return val; } public static float ToFloat(this object target) { _ = float.TryParse(target.ToString(), out var val); return val; } public static double ToDouble(this object target) { _ = double.TryParse(target.ToString(), out var val); return val; } public static decimal ToDecimal(this object target) { _ = decimal.TryParse(target.ToString(), out var val); return val; } #endregion /// /// 文字配列から文字列 /// #region CharsToString public static string CharsToString(this IEnumerable n) { return string.Join("", n); } #endregion /// /// 間に含まれているかどうか /// /// true:以上以下,false:超過未満 #region Between public static bool Between(this T target, T item1, T item2, bool isInclude = true) where T : IComparable { var low = item1; var high = item2; if (low.CompareTo(high) > 0) { low = item2; high = item1; } if (isInclude) return target.CompareTo(low) >= 0 && target.CompareTo(high) <= 0; else return target.CompareTo(low) > 0 && target.CompareTo(high) < 0; } #endregion /// /// 交換(値型,構造体のみ) /// #region Swap public static void Swap(ref T target, ref T item) where T : struct { (target, item) = (item, target); } #endregion /// /// 順列列挙 /// /// 各要素自身の重複 #region Permutation public static IEnumerable Permutation(this IEnumerable items, int k, bool withRepetition = false) { if (k == 1) { foreach (var item in items) { yield return new T[] { item }; } yield break; } foreach (var item in items) { var leftside = new T[] { item }; var unused = withRepetition ? items : items.Except(leftside); foreach (var rightside in Permutation(unused, k - 1, withRepetition)) { yield return leftside.Concat(rightside).ToArray(); } } } #endregion /// /// 組み合わせ列挙 /// /// 各要素自身の重複 #region Combination public static IEnumerable Combination(this IEnumerable items, int k, bool withRepetition = false) { if (k == 1) { foreach (var item in items) yield return new T[] { item }; yield break; } foreach (var item in items) { var leftside = new T[] { item }; var unused = withRepetition ? items : items.SkipWhile(e => !e.Equals(item)).Skip(1).ToList(); foreach (var rightside in Combination(unused, k - 1, withRepetition)) { yield return leftside.Concat(rightside).ToArray(); } } } #endregion /// /// フィボナッチ /// /// 初項0 #region GetFibonacci public static long GetFibonacci(int n, bool isZeroStart = true) { if (n == 0) return isZeroStart ? 0 : 1; if (n == 1) return 1; var dp = new long[n + 1]; dp[0] = isZeroStart ? 0 : 1; dp[1] = 1; for (var i = 2; i <= n; i++) { dp[i] = dp[i - 1] + dp[i - 2]; } return dp[n]; } #endregion /// /// Lower_Bound /// {0,0,1,1,2,2,3,3}(2)なら return 4 /// /// value以上の値の最小インデックス,無ければ-1 #region BoundLower public static int BoundLower(this IList values, T value) { if (values.Count == 0) return -1; var cmp = Comparer.Default; if (cmp.Compare(values[0], values.Last()) > 0) throw new Exception("BoundLower"); if (cmp.Compare(values[0], value) >= 0) return 0; if (cmp.Compare(values.Last(), value) < 0) return -1; var left = 0; var right = values.Count - 1; while (left <= right) { var mid = (left + right) / 2; // 中点取得 var res = cmp.Compare(values[mid], value); if (res == -1) left = mid + 1; else right = mid - 1; } return left; } #endregion /// /// Lower_Bound_Desc /// {3,3,2,2,1,1,0,0}(2)なら return 2 /// /// value以下の最小インデックス,無ければ-1 #region BoundLowerDesc public static int BoundLowerDesc(this IList values, T value) { if (values.Count == 0) return -1; var cmp = Comparer.Default; if (cmp.Compare(values[0], values.Last()) < 0) throw new Exception("BoundLowerDesc"); if (cmp.Compare(values[0], value) <= 0) return 0; if (cmp.Compare(values.Last(), value) > 0) return -1; var left = 0; var right = values.Count - 1; while (left <= right) { var mid = (left + right) / 2; // 中点取得 var res = cmp.Compare(values[mid], value); if (res == 1) left = mid + 1; else right = mid - 1; } return left; } #endregion /// /// Upper_Bound /// {0,0,1,1,2,2,3,3}(2)なら return 6 /// /// valueより大きい最小インデックス,無ければ-1 #region BoundUpper public static int BoundUpper(this IList values, T value) { if (values.Count == 0) return -1; var cmp = Comparer.Default; if (cmp.Compare(values[0], values.Last()) > 0) throw new Exception("BoundUpper"); if (cmp.Compare(values[0], value) > 0) return 0; if (cmp.Compare(values[values.Count - 1], value) <= 0) return -1; var left = 0; var right = values.Count - 1; while (left <= right) { var mid = (left + right) / 2; // 中点取得 var res = cmp.Compare(values[mid], value); if (res <= 0) left = mid + 1; else right = mid - 1; } return left; } #endregion /// /// Upper_Bound_Desc /// {3,3,2,2,1,1,0,0}(2)なら return 4 /// /// value未満の最小インデックス,無ければ-1 #region BoundUpperDesc public static int BoundUpperDesc(this IList values, T value) { if (values.Count == 0) return -1; var cmp = Comparer.Default; if (cmp.Compare(values[0], values.Last()) < 0) throw new Exception("BoundUpperDesc"); if (cmp.Compare(values[0], value) < 0) return 0; if (cmp.Compare(values.Last(), value) >= 0) return -1; var left = 0; var right = values.Count - 1; while (left <= right) { var mid = (left + right) / 2; // 中点取得 var res = cmp.Compare(values[mid], value); if (res >= 0) left = mid + 1; else right = mid - 1; } return left; } #endregion /// /// 距離取得 /// /// true:直線距離,false:縦横距離 #region GetDistance public static decimal GetDistance(this (T, T) point1, (T, T) point2, bool isEuclidean = true) { var X = Abs(point1.Item1.ToDecimal() - point2.Item1.ToDecimal()); var Y = Abs(point1.Item2.ToDecimal() - point2.Item2.ToDecimal()); return isEuclidean ? Sqrt((X * X + Y * Y).ToDouble()).ToDecimal() : X + Y; } #endregion /// /// bit全探索用のリスト作成 /// #region CreateBitArrays public static IEnumerable CreateBitArrays(this int n) { var list = new List(); for (var bit = 0; bit < (1 << n); bit++) { list.Add(new bool[n]); for (var i = 0; i < n; i++) { list[bit][i] = (bit & (1 << i)) != 0; } } return list.AsEnumerable(); } #endregion /// /// N個からR個選ぶ順列 /// #region NPR public static long NPR(this int num1, int num2) { if (num1 < num2) return 0; var ans = 1L; for (var i = 0; i < num2; i++) ans *= num1 - i; return ans; } #endregion /// /// N個からR個選ぶ組み合わせ /// #region NCR public static long NCR(this int num1, int num2) { if (num1 < num2) return 0; if (num2 > num1 / 2) num2 = num1 - num2; var ans = 1L; for (var i = 0; i < num2; i++) ans *= num1 - i; for (var i = num2; i >= 2; i--) ans /= i; return ans; } #endregion } #endregion /// /// 標準入力クラス /// #region Scanner class Scanner { string[] _str; int _int; public Scanner() { _str = new string[0]; _int = 0; } public string Next() { if (_int < _str.Length) return _str[_int++]; var st = ReadLine()?.Trim(); while (st == "") st = ReadLine(); if (st != null) _str = Split(st, ' '); if (_str.Length == 0) return Next(); _int = 0; return _str[_int++]; } public string NextLine() { if (_int < _str.Length) { var s = " " + string.Join(" ", _str.Skip(_int++)); _str = new string[0]; return s; } var st = ReadLine()?.Trim(); while (st == "") st = ReadLine()?.Trim(); _str = new string[] { st }; _int = 0; return _str[_int++]; } private static string[] Split(string st, char sep = ' ') { var sb = new StringBuilder(); var li = new List(); for (var i = 0; i < st.Length; i++) { if (st[i] == sep) { if (sb.ToString() != "") li.Add(sb.ToString()); sb.Clear(); } else { sb.Append(st[i]); } } if (sb.ToString() != "") li.Add(sb.ToString()); return li.ToArray(); } public int NextInt() { return int.Parse(Next()); } public long NextLong() { return long.Parse(Next()); } public double NextDouble() { return double.Parse(Next()); } } #endregion /// /// 素数 /// #region PrimeNumber public static class PrimeNumber { public static long[] Primes = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 }; /// /// 素数判定 /// #region 素数判定 public static bool IsPrime(long num) { if (num <= 1) return false; if (Primes.Contains(num)) return true; if (Primes.Any(x => num % x == 0)) return false; for (var i = 101L; i * i <= num; i += 2) { if (num % i == 0) return false; } return true; } #endregion /// /// 素因数分解 /// #region 素因数分解 public static List PrimeFactorization(long n) { if (n <= 1) return new List(); var primes = new List(); for (var i = 2L; i * i <= n; i++) { if (!IsPrime(i)) continue; var e = (long)0; while (n % i == 0) { e++; n /= i; } primes.Add(new long[] { i, e }); } if (n != 1) primes.Add(new long[] { n, 1 }); return primes; } #endregion /// /// 2数の最大公約数 /// #region 最大公約数 public static long GreatestCommonDivisor(long num1, long num2) { var low = num1 <= num2 ? num1 : num2; var high = num1 <= num2 ? num2 : num1; var temp = (long)0; while (true) { if (high % low == 0) return low; temp = high % low; high = low; low = temp; } } #endregion /// /// 2数の最小公倍数 /// #region 最小公倍数 public static long LeastCommonMultiple(long num1, long num2) { return num1 * num2 / GreatestCommonDivisor(num1, num2); } #endregion } #endregion }