Cod sursa(job #3157707)

Utilizator AztecaVlad Tutunaru 2 Azteca Data 16 octombrie 2023 18:26:57
Problema Indep Scor 15
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 11.28 kb
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

/**
 Alo delta force, alo baza baza
 sichi sichi sichi bum
 a tras fata un fum, se misca pe rup tutun
 da din ea de iese fum
 sichi sichi bam
 da-te la asta man
 zici ca e aeroplan
 avion america

 ia uitati-va la ea... cum face cumpana
 cum se-ndoaie cum se-nmoaie
 zici ca-i gata de bataie
 imbracata in soldat, trage foc automat
 tatuata pe picior, cu cartuse si pistol

 ...

 luati-o de aici ca mor,scoateti-o pe coridor
 ca da drumul la motor, la motor cu reactor //// nu mai stiu unde venea replica asta

 ...

 are are buze parca sunt doua ventuze
 si cu sanii aia mari zici ca sunt doua obuze
 cum iti baga, rpin dotare, funduuuuul ala mare si baga in functiune
 e direct infractiune
 ratatatatata, femeia arata tank tank dala blindat se-nvarte ca un bumerang
 cu motorul ala nervos se misca bine si-o face frumos
 cand pe fata... cand pe dos

 din doi timpi si trei miscari, a fumat doua tigari
 a golit si trei pahare
 gata de decolare
 are sutien mortal cu pene de papagal
 si bikinii mici mici mici, luat-o fratilor de aici
**/

const int base = 1000000000;
const int base_digits = 9;

struct bigint {
  vector<int> a;
  int sign;

  bigint() :
    sign(1) {
  }

  bigint(long long v) {
    *this = v;
  }

  bigint(const string &s) {
    read(s);
  }

  void operator=(const bigint &v) {
    sign = v.sign;
    a = v.a;
  }

  void operator=(long long v) {
    sign = 1;
    if (v < 0)
      sign = -1, v = -v;
    for (; v > 0; v = v / base)
      a.push_back(v % base);
  }

  bigint operator+(const bigint &v) const {           //Addition Operation
    if (sign == v.sign) {
      bigint res = v;
      for (int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) {
        if (i == (int) res.a.size())
          res.a.push_back(0);
        res.a[i] += carry + (i < (int) a.size() ? a[i] : 0);
        carry = res.a[i] >= base;
        if (carry)
          res.a[i] -= base;
      }
      return res;
    }
    return *this - (-v);
  }

  bigint operator-(const bigint &v) const {           //Subtraction Function
    if (sign == v.sign) {
      if (abs() >= v.abs()) {
        bigint res = *this;
        for (int i = 0, carry = 0; i < (int) v.a.size() || carry; ++i) {
          res.a[i] -= carry + (i < (int) v.a.size() ? v.a[i] : 0);
          carry = res.a[i] < 0;
          if (carry)
            res.a[i] += base;
        }
        res.trim();
        return res;
      }
      return -(v - *this);
    }
    return *this + (-v);
  }

  void operator*=(int v) {                    //Multiplication Function
    if (v < 0)
      sign = -sign, v = -v;
    for (int i = 0, carry = 0; i < (int) a.size() || carry; ++i) {
      if (i == (int) a.size())
        a.push_back(0);
      long long cur = a[i] * (long long) v + carry;
      carry = (int) (cur / base);
      a[i] = (int) (cur % base);
      //asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base));
    }
    trim();
  }

  bigint operator*(int v) const {
    bigint res = *this;
    res *= v;
    return res;
  }

  friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) {
    int norm = base / (b1.a.back() + 1);
    bigint a = a1.abs() * norm;
    bigint b = b1.abs() * norm;
    bigint q, r;
    q.a.resize(a.a.size());
    for (int i = a.a.size() - 1; i >= 0; i--) {
      r *= base;
      r += a.a[i];
      int s1 = r.a.size() <= b.a.size() ? 0 : r.a[b.a.size()];
      int s2 = r.a.size() <= b.a.size() - 1 ? 0 : r.a[b.a.size() - 1];
      int d = ((long long) base * s1 + s2) / b.a.back();
      r -= b * d;
      while (r < 0)
        r += b, --d;
      q.a[i] = d;
    }

    q.sign = a1.sign * b1.sign;
    r.sign = a1.sign;
    q.trim();
    r.trim();
    return make_pair(q, r / norm);
  }

  bigint operator/(const bigint &v) const {               //Division Function
    return divmod(*this, v).first;
  }

  bigint operator%(const bigint &v) const {               //Modulus Operation
    return divmod(*this, v).second;
  }

  void operator/=(int v) {                                //Shorthand Operation
    if (v < 0)
      sign = -sign, v = -v;
    for (int i = (int) a.size() - 1, rem = 0; i >= 0; --i) {
      long long cur = a[i] + rem * (long long) base;
      a[i] = (int) (cur / v);
      rem = (int) (cur % v);
    }
    trim();
  }

  bigint operator/(int v) const {
    bigint res = *this;
    res /= v;
    return res;
  }

  int operator%(int v) const {
    if (v < 0)
      v = -v;
    int m = 0;
    for (int i = a.size() - 1; i >= 0; --i)
      m = (a[i] + m * (long long) base) % v;
    return m * sign;
  }

  void operator+=(const bigint &v) {
    *this = *this + v;
  }
  void operator-=(const bigint &v) {
    *this = *this - v;
  }
  void operator*=(const bigint &v) {
    *this = *this * v;
  }
  void operator/=(const bigint &v) {
    *this = *this / v;
  }

  bool operator<(const bigint &v) const {
    if (sign != v.sign)
      return sign < v.sign;
    if (a.size() != v.a.size())
      return a.size() * sign < v.a.size() * v.sign;
    for (int i = a.size() - 1; i >= 0; i--)
      if (a[i] != v.a[i])
        return a[i] * sign < v.a[i] * sign;
    return false;
  }

  bool operator>(const bigint &v) const {
    return v < *this;
  }
  bool operator<=(const bigint &v) const {
    return !(v < *this);
  }
  bool operator>=(const bigint &v) const {
    return !(*this < v);
  }
  bool operator==(const bigint &v) const {
    return !(*this < v) && !(v < *this);
  }
  bool operator!=(const bigint &v) const {
    return *this < v || v < *this;
  }

  void trim() {
    while (!a.empty() && !a.back())
      a.pop_back();
    if (a.empty())
      sign = 1;
  }

  bool isZero() const {
    return a.empty() || (a.size() == 1 && !a[0]);
  }

  bigint operator-() const {
    bigint res = *this;
    res.sign = -sign;
    return res;
  }

  bigint abs() const {
    bigint res = *this;
    res.sign *= res.sign;
    return res;
  }

  long long longValue() const {
    long long res = 0;
    for (int i = a.size() - 1; i >= 0; i--)
      res = res * base + a[i];
    return res * sign;
  }

  friend bigint gcd(const bigint &a, const bigint &b) {           //GCD Function(Euler Algorithm)
    return b.isZero() ? a : gcd(b, a % b);
  }
  friend bigint lcm(const bigint &a, const bigint &b) {           //Simple LCM Operation
    return a / gcd(a, b) * b;
  }

  void read(const string &s) {                                //Reading a Big Integer
    sign = 1;
    a.clear();
    int pos = 0;
    while (pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) {
      if (s[pos] == '-')
        sign = -sign;
      ++pos;
    }
    for (int i = s.size() - 1; i >= pos; i -= base_digits) {
      int x = 0;
      for (int j = max(pos, i - base_digits + 1); j <= i; j++)
        x = x * 10 + s[j] - '0';
      a.push_back(x);
    }
    trim();
  }

  friend istream& operator>>(istream &stream, bigint &v) {
    string s;
    stream >> s;
    v.read(s);
    return stream;
  }

  friend ostream& operator<<(ostream &stream, const bigint &v) {
    if (v.sign == -1)
      stream << '-';
    stream << (v.a.empty() ? 0 : v.a.back());
    for (int i = (int) v.a.size() - 2; i >= 0; --i)
      stream << setw(base_digits) << setfill('0') << v.a[i];
    return stream;
  }

  static vector<int> convert_base(const vector<int> &a, int old_digits, int new_digits) {
    vector<long long> p(max(old_digits, new_digits) + 1);
    p[0] = 1;
    for (int i = 1; i < (int) p.size(); i++)
      p[i] = p[i - 1] * 10;
    vector<int> res;
    long long cur = 0;
    int cur_digits = 0;
    for (int i = 0; i < (int) a.size(); i++) {
      cur += a[i] * p[cur_digits];
      cur_digits += old_digits;
      while (cur_digits >= new_digits) {
        res.push_back(int(cur % p[new_digits]));
        cur /= p[new_digits];
        cur_digits -= new_digits;
      }
    }
    res.push_back((int) cur);
    while (!res.empty() && !res.back())
      res.pop_back();
    return res;
  }

  typedef vector<long long> vll;

  static vll karatsubaMultiply(const vll &a, const vll &b) {      //Multiplication using Karatsuba Algorithm
    int n = a.size();
    vll res(n + n);
    if (n <= 32) {
      for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
          res[i + j] += a[i] * b[j];
      return res;
    }

    int k = n >> 1;
    vll a1(a.begin(), a.begin() + k);
    vll a2(a.begin() + k, a.end());
    vll b1(b.begin(), b.begin() + k);
    vll b2(b.begin() + k, b.end());

    vll a1b1 = karatsubaMultiply(a1, b1);
    vll a2b2 = karatsubaMultiply(a2, b2);

    for (int i = 0; i < k; i++)
      a2[i] += a1[i];
    for (int i = 0; i < k; i++)
      b2[i] += b1[i];

    vll r = karatsubaMultiply(a2, b2);
    for (int i = 0; i < (int) a1b1.size(); i++)
      r[i] -= a1b1[i];
    for (int i = 0; i < (int) a2b2.size(); i++)
      r[i] -= a2b2[i];

    for (int i = 0; i < (int) r.size(); i++)
      res[i + k] += r[i];
    for (int i = 0; i < (int) a1b1.size(); i++)
      res[i] += a1b1[i];
    for (int i = 0; i < (int) a2b2.size(); i++)
      res[i + n] += a2b2[i];
    return res;
  }

  bigint operator*(const bigint &v) const {
    vector<int> a6 = convert_base(this->a, base_digits, 6);
    vector<int> b6 = convert_base(v.a, base_digits, 6);
    vll a(a6.begin(), a6.end());
    vll b(b6.begin(), b6.end());
    while (a.size() < b.size())
      a.push_back(0);
    while (b.size() < a.size())
      b.push_back(0);
    while (a.size() & (a.size() - 1))
      a.push_back(0), b.push_back(0);
    vll c = karatsubaMultiply(a, b);
    bigint res;
    res.sign = sign * v.sign;
    for (int i = 0, carry = 0; i < (int) c.size(); i++) {
      long long cur = c[i] + carry;
      res.a.push_back((int) (cur % 1000000));
      carry = (int) (cur / 1000000);
    }
    res.a = convert_base(res.a, 6, base_digits);
    res.trim();
    return res;
  }
};

const int N = 500 + 7;
const int VAL = 1000 + 7;
bigint dp[N][VAL], up[N][VAL];
vector<int> divs[VAL], has[VAL];
int n;

signed main() {
#ifdef ONPC
  freopen("input.txt", "r", stdin);
#else
  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
  freopen("indep.in", "r", stdin);
  freopen("indep.out", "w", stdout);
#endif // ONPC

  {
    for (int i = 2; i < VAL; i++) {
      for (int j = i; j < VAL; j += i) {
        divs[j].push_back(i);
      }
    }
  }

  cin >> n;
  vector<int> a(n + 1);
  int mx = 0;
  for (int i = 1; i <= n; i++) {
    cin >> a[i];
    mx = max(mx, a[i]);
  }
  for (int i = 1; i <= n; i++) {
    dp[i][a[i]] = 1;
    for (auto &it : divs[a[i]]) {
      for (auto &pos : has[it]) {
        assert(a[pos] % it == 0);
        dp[i][it] = dp[i][it] + up[pos][it];
      }
    }
    for (auto &it : divs[a[i]]) {
      has[it].push_back(i);
    }
    for (int j = VAL - 1; j >= 1; j--) {
      up[i][j] = up[i][2 * j] + dp[i][j];
    }
  }
  bigint sol = 1;
  for (int i = 1; i <= n; i++) {
    sol = sol * 2;
  }
  sol = sol - 1;
  for (int i = 1; i <= n; i++) {
    for (int j = 2; j < VAL; j++) {
      sol = sol - dp[i][j];
    }
  }
  cout << sol << "\n";
  return 0;
}