Submission #31096016


Source Code Expand

#include <vector>
#include <numeric>
#include <set>
using i64 = long long;


struct osa_k {
  using int_type = int;
  std::vector<int_type> min_fact;

  // O(NlogN)
  static std::vector<int_type> min_prime_factor(int n) {
    std::vector<int_type> res(n);
    std::iota(std::begin(res), std::end(res), 0);
    for(int i = 2; i * i < n; i++) {
      if(res[i] < i) continue;
      for(int j = i * i; j < n; j += i) {
        if(res[j] == j) res[j] = i;
      }
    }
    return res;
  }

  void build(int n) {
    min_fact = min_prime_factor(n);
  }

  // O(logN)
  std::vector<std::pair<int_type, int>> prime_factors(int n) const {
    std::vector<std::pair<int_type, int>> res;
    while(n > 1) {
      if(res.empty() || res.back().first != min_fact[n]) {
        res.push_back({ min_fact[n], 0 });
      }
      res.back().second++;
      n /= min_fact[n];
    }
    return res;
  }
  
  // The divisors are not sorted
  // O(logN + |divisors|)
  template<class F>
  void enumerate_divisors(int n, F f) const {
    std::vector<std::pair<int_type, int>> prime_facts = prime_factors(n);
    if(prime_facts.empty()) {
      f(1);
      return;
    }
    std::vector<int> cnt(prime_facts.size());
    std::vector<int> acc(prime_facts.size(), 1);
    while(true){
      f(acc.front());
      int i = 0;
      for(; i < prime_facts.size(); i++) {
        if((cnt[i]++) == prime_facts[i].second) {
          cnt[i] = 0;
        }
        else {
          acc[i] *= prime_facts[i].first;
          break;
        }
      }
      if(i == prime_facts.size()) {
        break;
      }
      while(i --> 0) {
        acc[i] = acc[i + 1];
      }
    }
  }
};

#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
#define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
#define all(x) x.begin(),x.end()
#define STRINGIFY(n) #n
#define TOSTRING(n) STRINGIFY(n)
#define PREFIX "#" TOSTRING(__LINE__) "| "
#define debug(x) \
{ \
  std::cout << PREFIX << #x << " = " << x << std::endl; \
}
std::ostream& output_indent(std::ostream& os, int ind) {
  for(int i = 0; i < ind; i++) os << " ";
  return os;
}
template<class S, class T> std::ostream& operator<<(std::ostream& os, const std::pair<S, T>& p);
template<class T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v);
template<class S, class T> std::ostream& operator<<(std::ostream& os, const std::pair<S, T>& p) {
  return (os << "(" << p.first << ", " << p.second << ")");
}
template<class T> std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
  os << "[";
  for(int i = 0;i < v.size();i++) os << v[i] << ", ";
  return (os << "]");
}
template<class T>
static inline std::vector<T> ndvec(size_t&& n, T val) { return std::vector<T>(n, std::forward<T>(val)); }
template<class... Tail>
static inline auto ndvec(size_t&& n, Tail&&... tail) {
  return std::vector<decltype(ndvec(std::forward<Tail>(tail)...))>(n, ndvec(std::forward<Tail>(tail)...));
}

 
template<uint32_t M>
struct montgomery_modint {
  using Self = montgomery_modint<M>;
  using i32 = int32_t;
  using u32 = uint32_t;
  using u64 = uint64_t;
 
  static constexpr u32 get_r() {
    u32 res = M;
    for(int i = 0; i < 4; i++) res *= 2 - M * res;
    return res;
  }
  static constexpr u32 reduce(u64 a) {
    return (a + u64(u32(a) * u32(-r)) * M) >> 32;
  }
 
  static constexpr u32 r = get_r();
  static constexpr u32 n2 = -u64(M) % M;
 
  u32 a;
 
  constexpr montgomery_modint() : a(0) {}
  constexpr montgomery_modint(int64_t a) : a(reduce(u64(a % M + M) * n2)) {}
 
  constexpr u32 val() const {
    u32 res = reduce(a);
    return res >= M ? res - M : res;
  }
  constexpr Self pow(u64 r) const {
    Self ans(1); Self aa = *this;
    while(r) { if(r & 1) ans *= aa; aa *= aa; r >>= 1; }
    return ans;
  }
  constexpr Self inv() const { return this->pow(M - 2); }
  constexpr Self& operator+=(const Self& r) {
    if(i32(a += r.a - 2 * M) < 0) a += 2 * M;
    return *this;
  }
  constexpr Self& operator-=(const Self& r) {
    if(i32(a -= r.a) < 0) a += 2 * M;
    return *this;
  }
  constexpr Self& operator*=(const Self& r) {
    a = reduce(u64(a) * r.a);
    return *this;
  }
  constexpr Self& operator/=(const Self& r) {
    *this *= r.inv();
    return *this;
  }
  constexpr Self operator+(const Self r) const { return Self(*this) += r; }
  constexpr Self operator-(const Self r) const { return Self(*this) -= r; }
  constexpr Self operator-() const { return Self() - Self(*this); }
  constexpr Self operator*(const Self r) const { return Self(*this) *= r; }
  constexpr Self operator/(const Self r) const { return Self(*this) /= r; }
  constexpr bool operator==(const Self& r) const {
    return (a >= M ? a - M : a) == (r.a >= M ? r.a - M : r.a);
  }
  constexpr bool operator!=(const Self& r) const {
    return (a >= M ? a - M : a) == (r.a >= M ? r.a - M : r.a);
  }
};
 
template<uint32_t M>
std::ostream& operator<<(std::ostream& os, const montgomery_modint<M>& m) {
  return os << m.val();
}
template<uint32_t M>
std::istream& operator>>(std::istream& is, montgomery_modint<M>& m) {
  int64_t t;
  is >> t;
  m = montgomery_modint<M>(t);
  return is;
}
 
template<uint32_t mod>
using modint = montgomery_modint<mod>;
 
 
 
using fp = modint<998244353>;
 
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
 
template <class T>
void divisor_transform(vector<T> &a) {
    int n = a.size();
    vector<bool> sieve(n, true);
    for (int p = 2; p < n; ++p) {
        if (sieve[p]) {
            for (int k = 1; k * p < n; ++k) {
                sieve[k * p] = false;
                a[k * p] += a[k];
            }
        }
    }
    for (int i = 0; ++i != n;) {
        a[i] += a[0];
    }
}
 
template <class T>
void inverse_divisor_transform(vector<T> &a) {
    int n = a.size();
    vector<bool> sieve(n, true);
    for (int i = 0; ++i != n;) {
        a[i] -= a[0];
    }
    for (int p = 2; p < n; ++p) {
        if (sieve[p]) {
            for (int k = (n - 1) / p; k != 0; --k) {
                sieve[k * p] = false;
                a[k * p] -= a[k];
            }
        }
    }
 
}
 
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
 
template <class T>
void multiple_transform(vector<T> &a) {
    int n = a.size();
    vector<bool> sieve(n, true);
    for (int p = 2; p < n; ++p) {
        if (sieve[p]) {
            for (int k = (n - 1) / p; k != 0; --k) {
                sieve[k * p] = false;
                a[k] += a[k * p];
            }
        }
    }
    for (int i = 0; ++i != n;) {
        a[i] += a[0];
    }
}
 
template <class T>
void inverse_multiple_transform(vector<T> &a) {
    int n = a.size();
    vector<bool> sieve(n, true);
    for (int i = 0; ++i != n;) {
        a[i] -= a[0];
    }
    for (int p = 2; p < n; ++p) {
        if (sieve[p]) {
            for (int k = 1; k * p < n; ++k) {
                sieve[k * p] = false;
                a[k] -= a[k * p];
            }
        }
    }
}
 
constexpr i64 MAX = 1e6 + 1;
 
int main() {
  i64 N;
  cin.tie(nullptr);
  std::ios::sync_with_stdio(false);
  cin >> N;
  vector<i64> A(N);
  rep(i,0,N) cin >> A[i];

  osa_k osa;
  osa.build(MAX);
  vector<fp> S(MAX);
 
  vector<fp> ans(MAX);
 
  rep(i,0,N) {
    osa.enumerate_divisors(A[i], [&](int d) {
        S[d] += fp(A[i]);
        ans[d] -= fp(A[i]) * fp(A[i]);
    });
  }
  fp i2 = fp(2).inv();
  rep(g,1,MAX) {
    ans[g] += S[g] * S[g];
    ans[g] *= i2;
  }
 
  inverse_multiple_transform(ans);
 
  fp res;
  rep(g,1,MAX) {
    res += fp(g).inv() * ans[g];
  }
  cout << res << endl;
}

Submission Info

Submission Time
Task C - LCMs
User niuez
Language C++ (GCC 9.2.1)
Score 700
Code Size 7852 Byte
Status AC
Exec Time 222 ms
Memory 16728 KiB

Compile Error

./Main.cpp: In function ‘int main()’:
./Main.cpp:77:28: warning: unnecessary parentheses in declaration of ‘i’ [-Wparentheses]
   77 | #define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
      |                            ^
./Main.cpp:275:3: note: in expansion of macro ‘rep’
  275 |   rep(i,0,N) cin >> A[i];
      |   ^~~
./Main.cpp:77:28: warning: unnecessary parentheses in declaration of ‘i’ [-Wparentheses]
   77 | #define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
      |                            ^
./Main.cpp:283:3: note: in expansion of macro ‘rep’
  283 |   rep(i,0,N) {
      |   ^~~
./Main.cpp:77:28: warning: unnecessary parentheses in declaration of ‘g’ [-Wparentheses]
   77 | #define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
      |                            ^
./Main.cpp:290:3: note: in expansion of macro ‘rep’
  290 |   rep(g,1,MAX) {
      |   ^~~
./Main.cpp:77:28: warning: unnecessary parentheses in declaration of ‘g’ [-Wparentheses]
   77 | #define rep(i,s,e) for(i64 (i) = (s);(i) < (e);(i)++)
      |                            ^
./Main.cpp:298:3: note: in expansion of macro ‘rep’
  298 |   rep(g,1,MAX) {
      |   ^~~
./Main.cpp: In instantiation of ‘void osa_k::enumerate_divisors(int, F) const [with F = main()::<lambda(int)>]’:
./Main.cpp:287:6:   required from here
./Main.cpp:55:15: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
   55 |       for(; i < prime_facts.size(); i++) {
      |             ~~^~~~~~~~~~~~~~~~~~~~
./Main.cpp:64:12: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::pair<int, int> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
   64 |       if(i == prime_facts.size()) {
      |          ~~^~~~~~~~~~~~~~~~~~~~~

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 134 ms 15104 KiB
01-02.txt AC 172 ms 15904 KiB
01-03.txt AC 202 ms 16244 KiB
01-04.txt AC 133 ms 15048 KiB
01-05.txt AC 193 ms 16292 KiB
01-06.txt AC 168 ms 15828 KiB
01-07.txt AC 157 ms 15440 KiB
01-08.txt AC 181 ms 16032 KiB
01-09.txt AC 160 ms 15596 KiB
01-10.txt AC 205 ms 16724 KiB
01-11.txt AC 222 ms 16576 KiB
01-12.txt AC 201 ms 16612 KiB
01-13.txt AC 216 ms 16628 KiB
01-14.txt AC 199 ms 16728 KiB
01-15.txt AC 218 ms 16672 KiB
01-16.txt AC 200 ms 16652 KiB
01-17.txt AC 215 ms 16576 KiB
01-18.txt AC 214 ms 16580 KiB
sample-01.txt AC 133 ms 15156 KiB
sample-02.txt AC 133 ms 15048 KiB
sample-03.txt AC 133 ms 14948 KiB