Submission #7887729


Source Code Expand

Copy
//#define NDEBUG
#include <cstddef>
#include <cstdint>
#include <iostream>
#include <iterator>
#include <vector>

namespace n91 {

  using i8 = std::int_fast8_t;
  using i32 = std::int_fast32_t;
  using i64 = std::int_fast64_t;
  using u8 = std::uint_fast8_t;
  using u32 = std::uint_fast32_t;
  using u64 = std::uint_fast64_t;
  using isize = std::ptrdiff_t;
  using usize = std::size_t;

  constexpr usize operator"" _z(unsigned long long x) noexcept {
    return static_cast<usize>(x);
  }

  template <class T> class integral_iterator {
  public:
    using difference_type = T;
    using value_type = T;
    using pointer = const value_type*;
    using reference = value_type;
    using iterator_category = std::random_access_iterator_tag;

  private:
    using self_type = integral_iterator<value_type>;
    value_type i;

  public:
    constexpr integral_iterator() noexcept : i() {}
    explicit constexpr integral_iterator(const value_type i) noexcept : i(i) {}
    constexpr self_type operator++(int) noexcept { return self_type(i++); }
    constexpr self_type operator--(int) noexcept { return self_type(i--); }
    constexpr self_type operator[](const difference_type rhs) const noexcept {
      return self_type(i + rhs);
    }
    constexpr self_type& operator++() noexcept {
      ++i;
      return *this;
    }
    constexpr self_type& operator--() noexcept {
      --i;
      return *this;
    }
    constexpr reference operator*() const noexcept { return i; }
    constexpr self_type operator+(const difference_type rhs) const noexcept {
      return self_type(i + rhs);
    }
    constexpr self_type operator-(const difference_type rhs) const noexcept {
      return self_type(i - rhs);
    }
    constexpr difference_type operator-(const self_type rhs) const noexcept {
      return i - rhs.i;
    }
    constexpr bool operator<(const self_type rhs) const noexcept {
      return i < rhs.i;
    }
    constexpr bool operator<=(const self_type rhs) const noexcept {
      return i <= rhs.i;
    }
    constexpr bool operator>(const self_type rhs) const noexcept {
      return i > rhs.i;
    }
    constexpr bool operator>=(const self_type rhs) const noexcept {
      return i >= rhs.i;
    }
    constexpr bool operator==(const self_type rhs) const noexcept {
      return i == rhs.i;
    }
    constexpr bool operator!=(const self_type rhs) const noexcept {
      return i != rhs.i;
    }
    constexpr self_type& operator+=(const difference_type rhs) noexcept {
      i += rhs;
      return *this;
    }
    constexpr self_type& operator-=(const difference_type rhs) noexcept {
      i -= rhs;
      return *this;
    }
  };
  template <class T>
  constexpr integral_iterator<T> make_int_itr(const T i) noexcept {
    return integral_iterator<T>(i);
  }
  class rep {
    const usize f, l;

  public:
    constexpr rep(const usize f, const usize l) noexcept : f(f), l(l) {}
    constexpr auto begin() const noexcept { return make_int_itr(f); }
    constexpr auto end() const noexcept { return make_int_itr(l); }
  };
  class revrep {
    const usize f, l;

  public:
    revrep(const usize f, const usize l) noexcept : f(l), l(f) {}
    auto begin() const noexcept {
      return std::make_reverse_iterator(make_int_itr(f));
    }
    auto end() const noexcept {
      return std::make_reverse_iterator(make_int_itr(l));
    }
  };
  template <class T> auto md_vec(const usize n, const T& value) {
    return std::vector<T>(n, value);
  }
  template <class... Args> auto md_vec(const usize n, Args... args) {
    return std::vector<decltype(md_vec(args...))>(n, md_vec(args...));
  }
  template <class T> constexpr T difference(const T& a, const T& b) {
    return a < b ? b - a : a - b;
  }
  template <class T> T scan() {
    T ret;
    std::cin >> ret;
    return ret;
  }

} // namespace n91
#include <cstdint>

namespace n91 {

  constexpr std::uint_fast64_t totient(std::uint_fast64_t x) noexcept {
    using u64 = std::uint_fast64_t;
    u64 ret = x;
    for (u64 i = static_cast<u64>(2); i * i <= x; ++i) {
      if (x % i == static_cast<u64>(0)) {
        ret -= ret / i;
        x /= i;
        while (x % i == static_cast<u64>(0)) {
          x /= i;
        }
      }
    }
    if (x != static_cast<u64>(1)) {
      ret -= ret / x;
    }
    return ret;
  }

  template <std::uint_fast64_t Modulus,
    std::uint_fast64_t InverseExp =
    totient(Modulus) - static_cast<std::uint_fast64_t>(1)>
    class modint {
    using u64 = std::uint_fast64_t;

    static_assert(Modulus < static_cast<u64>(1) << static_cast<u64>(32),
      "Modulus must be less than 2**32");

    u64 a;

    constexpr modint& negate() noexcept {
      if (a != static_cast<u64>(0)) {
        a = Modulus - a;
      }
      return *this;
    }

    public:
      constexpr modint(const u64 x = static_cast<u64>(0)) noexcept
        : a(x% Modulus) {}
      constexpr u64& value() noexcept { return a; }
      constexpr const u64& value() const noexcept { return a; }
      constexpr modint operator+() const noexcept { return modint(*this); }
      constexpr modint operator-() const noexcept { return modint(*this).negate(); }
      constexpr modint operator+(const modint rhs) const noexcept {
        return modint(*this) += rhs;
      }
      constexpr modint operator-(const modint rhs) const noexcept {
        return modint(*this) -= rhs;
      }
      constexpr modint operator*(const modint rhs) const noexcept {
        return modint(*this) *= rhs;
      }
      constexpr modint operator/(const modint rhs) const noexcept {
        return modint(*this) /= rhs;
      }
      constexpr modint& operator+=(const modint rhs) noexcept {
        a += rhs.a;
        if (a >= Modulus) {
          a -= Modulus;
        }
        return *this;
      }
      constexpr modint& operator-=(const modint rhs) noexcept {
        if (a < rhs.a) {
          a += Modulus;
        }
        a -= rhs.a;
        return *this;
      }
      constexpr modint& operator*=(const modint rhs) noexcept {
        a = a * rhs.a % Modulus;
        return *this;
      }
      constexpr modint& operator/=(modint rhs) noexcept {
        u64 exp = InverseExp;
        while (exp) {
          if (exp % static_cast<u64>(2) != static_cast<u64>(0)) {
            *this *= rhs;
          }
          rhs *= rhs;
          exp /= static_cast<u64>(2);
        }
        return *this;
      }
      constexpr bool operator==(const modint rhs) const noexcept {
        return a == rhs.a;
      }
      constexpr bool operator!=(const modint rhs) const noexcept {
        return a != rhs.a;
      }
  };

  template <class T, std::uint_fast64_t v> class modint_constant {
  public:
    static constexpr T value = static_cast<T>(v);

    using value_type = T;
  };

} // namespace n91
#include <cassert>
#include <cstddef>
#include <numeric>
#include <utility>
#include <vector>

namespace n91 {

  class prime_sieve {
  public:
    using size_type = std::size_t;

  private:
    std::vector<size_type> prime, factor;

  public:
    prime_sieve() {}
    explicit prime_sieve(const size_type size) : prime(), factor(size) {
      assert(size >= 2);
      std::iota(factor.begin(), factor.end(), static_cast<size_type>(0));
      factor[0] = 1;
      factor[1] = 0;
      prime.reserve(size);
      for (size_type i{ 2 }; i != size; ++i) {
        const size_type fi = factor[i];
        if (fi == i) {
          prime.push_back(i);
        }
        for (const size_type p : prime) {
          if (p > fi) {
            break;
          }
          const size_type ip = i * p;
          if (ip >= size) {
            break;
          }
          factor[ip] = p;
        }
      }
      prime.shrink_to_fit();
    }
    size_type len() const noexcept { return factor.size(); }
    bool is_prime(const size_type i) const noexcept {
      assert(i < len());
      return factor[i] == i;
    }
    std::vector<size_type> factorize(size_type i) const noexcept {
      assert(i != 0);
      std::vector<size_type> ret;
      while (i != 1) {
        ret.push_back(factor[i]);
        i /= factor[i];
      }
      return std::move(ret);
    }
    template <class C> void divisor_zeta(C& c) const noexcept {
      const size_type n{ c.size() };
      assert(n <= len());
      for (size_type i{ 0 }; i != prime.size() && prime[i] < n; ++i) {
        for (size_type j{ 1 }; j * prime[i] < n; ++j) {
          c[j * prime[i]] += c[j];
        }
      }
    }
    template <class C> void divisor_mobius(C& c) const noexcept {
      const size_type n{ c.size() };
      assert(n <= len());
      for (size_type i{ 0 }; i != prime.size() && prime[i] < n; ++i) {
        for (size_type j{ (n - 1) / prime[i] }; j != 0; --j) {
          c[j * prime[i]] -= c[j];
        }
      }
    }
    template <class C> void multiple_zeta(C& c) const noexcept {
      const size_type n{ c.size() };
      assert(n <= len());
      /*
      for (size_type i{0}; i != prime.size() && prime[i] < n; ++i) {
        for (size_type j{(n - 1) / prime[i]}; j != 0; --j) {
          c[j] += c[j * prime[i]];
        }
      }
      /*/
      for (const size_type p : prime) {
        if (p >= n) {
          break;
        }
        for (size_type i{ (n - 1) / p }, j{ i * p }; i != 0; --i, j -= p) {
          c[i] += c[j];
        }
      }
      //*/
    }
    template <class C> void multiple_mobius(C& c) const noexcept {
      const size_type n{ c.size() };
      assert(n <= len());
      /*
      for (size_type i{0}; i != prime.size() && prime[i] < n; ++i) {
        for (size_type j{1}; j * prime[i] < n; ++j) {
          c[j] -= c[j * prime[i]];
        }
      }
      /*/
      for (const size_type p : prime) {
        if (p >= n) {
          break;
        }
        for (size_type i{ 1 }, j{ p }; j < n; ++i, j += p) {
          c[i] -= c[j];
        }
      }
      //*/
    }
  };

} // namespace n91


#include <algorithm>
#include <iostream>
#include <utility>

namespace n91 {

  void main_() {
    static constexpr usize ALim = 1000001;
    using mint = modint<static_cast<u64>(998244353)>;
    const usize n = scan<usize>();
    std::vector<u64> a(n);
    for (auto& e : a) {
      std::cin >> e;
    }
    std::vector<mint> b(ALim);
    for (const auto e : a) {
      b[e] += static_cast<mint>(e);
    }
    const prime_sieve ps{ ALim };
    ps.multiple_zeta(b);
    for (auto& e : b) {
      e *= e;
    }
    ps.multiple_mobius(b);
    mint ans = static_cast<mint>(0);
    for (const auto e : a) {
      b[e] -= mint(e) * mint(e);
    }
    for (const auto i : rep(1_z, ALim)) {
      ans += b[i] / static_cast<mint>(i);
    }
    std::cout << (ans / mint(2)).value() << std::endl;
  }

} // namespace n91

int main() {
  n91::main_();
  return 0;
}

Submission Info

Submission Time
Task C - LCMs
User noshi91
Language C++14 (GCC 5.4.1)
Score 700
Code Size 11110 Byte
Status AC
Exec Time 223 ms
Memory 20608 KB

Judge Result

Set Name Sample All
Score / Max Score 0 / 0 700 / 700
Status
AC × 3
AC × 21
Set Name Test Cases
Sample sample-01.txt, sample-02.txt, sample-03.txt
All 01-01.txt, 01-02.txt, 01-03.txt, 01-04.txt, 01-05.txt, 01-06.txt, 01-07.txt, 01-08.txt, 01-09.txt, 01-10.txt, 01-11.txt, 01-12.txt, 01-13.txt, 01-14.txt, 01-15.txt, 01-16.txt, 01-17.txt, 01-18.txt, sample-01.txt, sample-02.txt, sample-03.txt
Case Name Status Exec Time Memory
01-01.txt AC 157 ms 19200 KB
01-02.txt AC 191 ms 18048 KB
01-03.txt AC 207 ms 20352 KB
01-04.txt AC 156 ms 17152 KB
01-05.txt AC 200 ms 18176 KB
01-06.txt AC 188 ms 17792 KB
01-07.txt AC 171 ms 18944 KB
01-08.txt AC 203 ms 18176 KB
01-09.txt AC 176 ms 19328 KB
01-10.txt AC 217 ms 18688 KB
01-11.txt AC 222 ms 18688 KB
01-12.txt AC 218 ms 20608 KB
01-13.txt AC 216 ms 18688 KB
01-14.txt AC 222 ms 18688 KB
01-15.txt AC 216 ms 18688 KB
01-16.txt AC 222 ms 18688 KB
01-17.txt AC 217 ms 20480 KB
01-18.txt AC 223 ms 20608 KB
sample-01.txt AC 155 ms 17152 KB
sample-02.txt AC 156 ms 17152 KB
sample-03.txt AC 155 ms 17152 KB