/// @file lcm.cc
/// @brief lcm の実装ファイル
/// @author Yusuke Matsunaga (松永 裕介)
///
/// Copyright (C) 2019 Yusuke Matsunaga
/// All rights reserved.


#include <iostream>
#include <vector>
#include <unordered_map>


using namespace std;

bool debug = false;

class ModInt
{
public:

  ModInt(long val = 0);

  ~ModInt() = default;

  operator long() const;

  void
  normalize();

  ModInt&
  operator+=(const ModInt& right);

  ModInt&
  operator-=(const ModInt& right);

  ModInt&
  operator*=(const ModInt& right);

  void
  div2();

private:

  long mVal;

public:

  static
  const long mMagicNumber = 998244353;

};

ModInt
operator+(const ModInt& left,
	  const ModInt& right);

ModInt
operator-(const ModInt& left,
	  const ModInt& right);

ModInt
operator*(const ModInt& left,
	  const ModInt& right);

ostream&
operator<<(ostream& s,
	   const ModInt& val)
{
  s << static_cast<long>(val);
  return s;
}

inline
ModInt::ModInt(long val) :
  mVal(val)
{
  normalize();
}

inline
ModInt::operator long() const
{
  return mVal;
}

inline
ModInt
operator+(const ModInt& left,
	  const ModInt& right)
{
  auto a = static_cast<long>(left);
  auto b = static_cast<long>(right);
  auto c = a + b;
  return ModInt{c};
}

inline
ModInt
operator-(const ModInt& left,
	  const ModInt& right)
{
  auto a = static_cast<long>(left);
  auto b = static_cast<long>(right);
  auto c = a - b;
  return ModInt{c};
}

inline
ModInt
operator*(const ModInt& left,
	  const ModInt& right)
{
  auto a = static_cast<long>(left);
  auto b = static_cast<long>(right);
  auto c = a * b;
  return ModInt{c};
}

inline
ModInt&
ModInt::operator+=(const ModInt& right)
{
  auto ans = (*this) + right;
  swap(*this, ans);
  return *this;
}

inline
ModInt&
ModInt::operator-=(const ModInt& right)
{
  auto ans = (*this) - right;
  swap(*this, ans);
  return *this;
}

inline
ModInt&
ModInt::operator*=(const ModInt& right)
{
  auto ans = (*this) * right;
  swap(*this, ans);
  return *this;
}

inline
void
ModInt::div2()
{
  if ( mVal % 2 == 1 ) {
    mVal += mMagicNumber;
  }
  mVal >>= 1;
}

inline
void
ModInt::normalize()
{
  mVal %= mMagicNumber;
  if ( mVal < 0 ) {
    mVal += mMagicNumber;
  }
}


int
main(int argc,
     char** argv)
{
  bool debug = false;

  int n;
  cin >> n;

  // 各要素の配列
  vector<int> A(n);

  // 最大値
  int max_val = 0;

  // 各値の出現回数
  vector<int> h(1000000, 0);
  for ( int i = 0; i < n; ++ i ) {
    int val;
    cin >> val;
    A[i] = val;
    ++ h[val];
    if ( max_val < val ) {
      max_val = val;
    }
  }

  // 出現回数に値自身を掛けたもの
  vector<ModInt> v_m(max_val + 1);
  for ( int i = 1; i <= max_val; ++ i ) {
    v_m[i] = ModInt{h[i] * i};
  }

  // Wd を計算する．
  vector<long> W(max_val + 1);
  W[0] = 0; // 例外：どうせ使わないけど．
  for ( int i = 1; i <= max_val; ++ i ) {
    W[i] = 1;
  }
  for ( int i = 1; i <= max_val; ++ i ) {
    // i の倍数の係数を調整する．
    for ( int j = i * 2; j <= max_val; j += i ) {
      W[j] = W[j] - W[i] * (j / i);
    }
  }

  ModInt ans = 0;
  for ( int x = 1; x <= max_val; ++ x ) {
    // x の倍数の対の値の総和を求める．
    ModInt sum1_m = 0;
    ModInt sum2_m = 0;
    ModInt diff_m = 0;
    for ( int val1 = x; val1 <= max_val; val1 += x ) {
      auto v1_m = v_m[val1];
      auto vx_m = ModInt{val1 / x};
      sum1_m += v1_m;
      sum2_m += ModInt{h[val1]} * vx_m;
      diff_m += v1_m * vx_m;
    }
    auto val_m = (sum1_m * sum2_m - diff_m);
    if ( val_m == 0 ) {
      // この x は使われない．
      continue;
    }
    val_m.div2();
    //cout << x << ": val = " << val << endl;
    auto tmp = ModInt{W[x]} * val_m;
    //cout << "w * val = " << tmp << endl;
    ans += tmp;
    //cout << "ans = " << ans << endl;
  }

  cout << ans << endl;

  return 0;
}


Measured memory_bytes: 20608