#include "bits/stdc++.h"

#include <iostream>

using namespace std;

//constexpr int MOD = 998244353;
#define ADD(a,b) (((u64)a + b)%MOD)
#define MUL(a,b) (((u64)a * b)%MOD)

template<typename T>
constexpr T Abs(T a) {
  return a > 0 ? a : -a;
}

template<typename T>
constexpr T manhattan(T x1, T y1, T x2, T y2) {
  return Abs(x1 - x2) + Abs(y1 - y2);
}

// C++17には標準で存在する。C++17以前で使いたい場合
template<class T>
constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
  assert(!(hi < lo));
  return (v < lo) ? lo : (hi < v) ? hi : v;
}

// 最大公約数を求める
template<typename T>
constexpr T GetGreatestCommonDivisor(T a, T b) {

  //cout << "gcd(" << a << "," << b << ") = ";

  if (b > a) {
    swap(a, b);
  }

  while (true) {
    T c = a % b;
    if (c == 0) break;

    a = move(b);
    b = move(c);
  }

  //cout << b << '\n';

  return b;
}

//
// 関数結果をキャッシュする
//
// 関数呼び出し結果をキャッシュし、2回目以降
// 同じ引数リストで呼び出した場合は、実際に関数を呼び出すのではなく
// かわりにキャッシュした結果から返す
//
// 引数が同じなら得られる答えが常に同じかつ、1回の計算コストが高く、
// 同じ引数で何度も呼び出す予定がある関数に最適
//
// ただしメモリを山のように食う
// メモリだけではなく、速度も扱い方によっては速くも遅くもなりうるので
// 速度を見つつ導入するかどうか考えながら注意して使うこと

#pragma once

#include <stdint.h>
#include <unordered_map>

using namespace std;

using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;

template<typename T>
class CachedFunction_u8_u8 {
public:
  CachedFunction_u8_u8(T(* const func)(u8, u8))
    : func(func) {

  }

  ~CachedFunction_u8_u8() {
    Release();
  }

  T Call(u8 a, u8 b) {
    u16 key;
    *((u8*)&key) = a;
    *((u8*)&key + 1) = b;

    auto it = results.find(key);
    if (it != results.end()) {
      return it->second;
    }

    return results[key] = func(a, b);
  }

  void Release() {
    results.clear();
  }

private:
  T(* const func)(u8, u8);
  unordered_map<u16, T> results;
};

template<typename T>
class CachedFunction_u32_u32 {
public:
  CachedFunction_u32_u32(T(* const func)(u32, u32))
    : func(func) {

  }

  ~CachedFunction_u32_u32() {
    Release();
  }

  T Call(u32 a, u32 b) {
    u64 key;
    *((u32*)&key) = a;
    *((u32*)&key + 1) = b;

    auto it = results.find(key);
    if (it != results.end()) {
      return it->second;
    }

    return results[key] = func(a, b);
  }

  void Release() {
    results.clear();
  }

private:
  T(* const func)(u32, u32);
  unordered_map<u64, T> results;
};

template<typename T>
class CachedFunction_u64_u64 {
public:
  CachedFunction_u64_u64(T(* const func)(u64, u64))
    : func(func) {
  }

  ~CachedFunction_u64_u64() {
    Release();
  }

  T Call(u64 a, u64 b) {
    auto i = results.find(a);
    if (i != results.end()) {
      auto j = i->second->find(b);
      if (j != i->second->end()) {
        return j->second;
      }

      return (*(i->second))[b] = func(a, b);
    }

    results[a] = new unordered_map<u64, T>;
    return (*results[a])[b] = func(a, b);
  }

  void Release() {
    for (auto& r : results) {
      r.second->clear();
      delete r.second;
    }
    results.clear();
  }

private:
  T(* const func)(u64, u64);
  unordered_map<u64, unordered_map<u64, T>*> results;
};

template<typename T>
CachedFunction_u8_u8<T> GetCachedFunction(T(* const func)(u8, u8)) {
  return move(CachedFunction_u8_u8<T>(func));
}

template<typename T>
CachedFunction_u32_u32<T> GetCachedFunction(T(* const func)(u32, u32)) {

  // move未対応だから実際はコピーされてしまうが、
  // この関数自体を呼ぶ回数自体は少ないので（得られたObjをたくさん使うので）
  // さして問題はないだろう
  return move(CachedFunction_u32_u32<T>(func));
}

template<typename T>
CachedFunction_u64_u64<T> GetCachedFunction(T(* const func)(u64, u64)) {
  return move(CachedFunction_u64_u64<T>(func));
}


using namespace std;

using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using i64 = int64_t;

#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define F0R(i,b) FOR(i,0,b)
#define RFO(i,a,b) for (int i = (b-1); i >= a; i--)
#define RF0(i,b) RFO(i,0,b)
#define F first
#define S second

auto gcd2 = GetCachedFunction(GetGreatestCommonDivisor<u8>);

#if 1
int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(false);

  int K;
  cin >> K;

  int r = 0;

  // 

  FOR(i, 1, K + 1) {

    FOR(j, 1, K + 1) {

      u8 a = i < j ?
        gcd2.Call(i, j) : gcd2.Call(j, i);

      FOR(k, 1, K + 1) {
        r += a < k ?
          gcd2.Call(a, k) : gcd2.Call(k, a);
      }
    }
  }

  cout << r;

}
#endif


Measured memory_bytes: 4260