#include using namespace std; using int128 = __int128_t; using int64 = long long; #define ALL(obj) (obj).begin(),(obj).end() /* * @title FastIO * @docs md/util/FastIO.md */ class FastIO{ private: inline static constexpr int ch_0='0'; inline static constexpr int ch_9='9'; inline static constexpr int ch_n='-'; inline static constexpr int ch_s=' '; inline static constexpr int ch_l='\n'; inline static void endline_skip(char& ch) { while(ch==ch_l) ch=getchar(); } template inline static void read_integer(T &x) { int neg=0; char ch; x=0; ch=getchar(); endline_skip(ch); if(ch==ch_n) neg=1,ch=getchar(); for(;(ch_0 <= ch && ch <= ch_9); ch = getchar()) x = x*10 + (ch-ch_0); if(neg) x*=-1; } template inline static void read_unsigned_integer(T &x) { char ch; x=0; ch=getchar(); endline_skip(ch); for(;(ch_0 <= ch && ch <= ch_9); ch = getchar()) x = x*10 + (ch-ch_0); } inline static void read_string(string &x) { char ch; x=""; ch=getchar(); endline_skip(ch); for(;(ch != ch_s && ch!=ch_l); ch = getchar()) x.push_back(ch); } inline static void read_char(char &x) { char ch; ch=getchar(); endline_skip(ch); for(;(ch != ch_s && ch!=ch_l); ch = getchar()) x=ch; } inline static char ar[40]; inline static char *ch_ar; template inline static void write_integer(T x) { ch_ar=ar; if(x< 0) putchar(ch_n), x=-x; if(x==0) putchar(ch_0); for(;x;x/=10) *ch_ar++=(ch_0+x%10); while(ch_ar--!=ar) putchar(*ch_ar); } public: inline static void read(int &x) {read_integer(x);} inline static void read(long long &x) {read_integer(x);} inline static void read(unsigned int &x) {read_unsigned_integer(x);} inline static void read(unsigned long long &x) {read_unsigned_integer(x);} inline static void read(string &x) {read_string(x);} inline static void read(char &x) {read_char(x);} inline static void read(__int128_t &x) {read_integer<__int128_t>(x);} inline static void write(__int128_t x) {write_integer<__int128_t>(x);} inline static void write(char x) {putchar(x);} }; #define read(arg) FastIO::read(arg) #define write(arg) FastIO::write(arg) template using priority_queue_reverse = priority_queue,greater>; constexpr int64 HIGHINF = 1'000'000'000'000'000'000LL; constexpr int64 LOWINF = 1'000'000'000'000'000LL; //' constexpr long double PI = 3.1415926535897932384626433L; template vector multivector(size_t N,T init){return vector(N,init);} template auto multivector(size_t N,T... t){return vector(N,multivector(t...));} template void corner(bool flg, T hoge) {if (flg) {cout << hoge << endl; exit(0);}} template ostream &operator<<(ostream &o, const pair&obj) {o << "{" << obj.first << ", " << obj.second << "}"; return o;} template ostream &operator<<(ostream &o, const map&obj) {o << "{"; for (auto &x : obj) o << " {" << x.first << " : " << x.second << "}" << ","; o << " }"; return o;} template ostream &operator<<(ostream &o, const set&obj) {o << "{"; for (auto itr = obj.begin(); itr != obj.end(); ++itr) o << (itr != obj.begin() ? ", " : "") << *itr; o << "}"; return o;} template ostream &operator<<(ostream &o, const multiset&obj) {o << "{"; for (auto itr = obj.begin(); itr != obj.end(); ++itr) o << (itr != obj.begin() ? ", " : "") << *itr; o << "}"; return o;} template ostream &operator<<(ostream &o, const vector&obj) {o << "{"; for (int i = 0; i < (int)obj.size(); ++i)o << (i > 0 ? ", " : "") << obj[i]; o << "}"; return o;} template ostream &operator<<(ostream &o, const deque&obj) {o << "{"; for (int i = 0; i < (int)obj.size(); ++i)o << (i > 0 ? ", " : "") << obj[i]; o << "}"; return o;} void print(void) {cout << endl;} template void print(Head&& head) {cout << head;print();} template void print(Head&& head, Tail&&... tail) {cout << head << " ";print(forward(tail)...);} template void chmax(T& a, const T b){a=max(a,b);} template void chmin(T& a, const T b){a=min(a,b);} vector split(const string &str, const char delemiter) {vector res;stringstream ss(str);string buffer; while( getline(ss, buffer, delemiter) ) res.push_back(buffer); return res;} inline constexpr int msb(int x) {return x?31-__builtin_clz(x):-1;} inline constexpr int64 ceil_div(const int64 a,const int64 b) {return (a+(b-1))/b;}// return ceil(a/b) void YN(bool flg) {cout << (flg ? "YES" : "NO") << endl;} void Yn(bool flg) {cout << (flg ? "Yes" : "No") << endl;} void yn(bool flg) {cout << (flg ? "yes" : "no") << endl;} /* * @title Prime - 高速素因数分解・ミラーラビン素数判定・Gcd・Lcm * @docs md/math/Prime.md */ class Prime{ using u128 = __uint128_t; using u64 = unsigned long long; using u32 = unsigned int; class MontgomeryMod { u64 mod,inv_mod,pow2_128; inline u64 reduce(const u128& val) { return (val + u128(u64(val) * u64(-inv_mod)) * mod) >> 64; } inline u128 init_reduce(const u64& val) { return reduce((u128(val) + mod) * pow2_128); } inline u64 mul_impl(const u64 l, const u64 r) { return reduce(u128(l)*r); } public: MontgomeryMod(const u64 mod):mod(mod),pow2_128(-u128(mod)%mod) { inv_mod = mod; for (int i = 0; i < 5; ++i) inv_mod *= 2 - mod * inv_mod; } //x^n % mod inline u64 pow(const u64& x, u64 n) { u64 mres = init_reduce(1); for (u64 mx = init_reduce(x); n > 0; n >>= 1, mx=mul_impl(mx,mx)) if (n & 1) mres = mul_impl(mres,mx); mres=reduce(mres); return mres >= mod ? mres - mod : mres; } inline u64 mul(const u64& l, const u64& r) { u64 ml=init_reduce(l),mr=init_reduce(r); u64 mres=reduce(mul_impl(ml,mr)); return mres >= mod ? mres - mod : mres; } inline u64 mmul(const u64& l, const u64& r) { u64 ml=init_reduce(l),mr=init_reduce(r); return mul_impl(ml,mr); } //NOTE lはmontgomery modの状態 inline u64 add(u64 ml, const u64& r) { u64 mr=init_reduce(r); if ((ml += mr) >= 2 * mod) ml -= 2 * mod; u64 mres=reduce(ml); return mres >= mod ? mres - mod : mres; } }; inline static constexpr long long pow_uint128(long long x, long long n, long long mod) { long long res = 1; for (x %= mod; n > 0; n >>= 1, x=(u128(x)*x)%mod) if (n & 1) res = (u128(res)*x)%mod; return res; } template inline static constexpr bool miller_rabin_uint128(const u64& n, const array& ar) { u32 i,s=0; u64 m = n - 1; for (;!(m&1);++s,m>>=1); MontgomeryMod mmod(n); for (const u64& a: ar) { if(a>=n) break; u64 r=pow_uint128(a,m,n); if(r != 1) { for(i=0; i inline static constexpr bool miller_rabin_montgomery(const u64& n, const array& ar) { u32 i,s=0; u64 m = n - 1; for (;!(m&1);++s,m>>=1); MontgomeryMod mmod(n); for (const u64& a: ar) { if(a>=n) break; u64 r=mmod.pow(a,m); if(r != 1) { for(i=0; i= m * K) n = s; } } return gcd_impl(m, n % m); } inline static constexpr long long pre(long long n, long long m) { long long t = n - m; for(int i = 0; t = n - m, i < 4; ++i) { (t < m ? n=m,m=t : n=t); if(!m) return n; } return gcd_impl(n, m); } inline static constexpr array ar1={2ULL, 7ULL, 61ULL}; inline static constexpr array ar2={2ULL,325ULL,9375ULL,28178ULL,450775ULL,9780504ULL,1795265022ULL}; inline static u64 rho(const u64& n){ if(miller_rabin(n)) return n; if((n&1) == 0) return 2; MontgomeryMod mmod(n); for(u64 c=1,x=2,y=2,d=0;;c++){ do{ x=mmod.add(mmod.mmul(x,x),c); y=mmod.add(mmod.mmul(y,y),c); y=mmod.add(mmod.mmul(y,y),c); d=gcd(x-y+n,n); }while(d==1); if(d factor(const u64& n, bool is_root) { if(n <= 1) return {}; u64 p = rho(n); if(p == n) return {p}; auto l = factor(p, false); auto r = factor(n / p, false); copy(r.begin(), r.end(), back_inserter(l)); if(is_root) sort(l.begin(),l.end()); return move(l); } inline static constexpr bool miller_rabin(const u64 n) { if(n <= 1) return false; if(n == 2) return true; if(n%2 == 0) return false; if(n == 3) return true; if(n%3 == 0) return false; if(n < 4759123141ULL) return miller_rabin_montgomery(n, ar1); if(n <= 1000'000'000'000'000'000ULL) miller_rabin_montgomery(n, ar2); return miller_rabin_uint128(n, ar2); } inline static vector> factorization_impl(const u64 n) { // queue q; q.push(n); // vector v; // while(q.size()) { // u64 tn = q.front(); q.pop(); // if(tn<=1) continue; // u64 p = rho(tn); // if(p!=tn) q.push(p),q.push(tn/p); // else v.push_back(p); // } auto v = factor(n, true); vector> vp; u64 prev = 0; for(u64& p:v) { if(p == prev) vp.back().second++; else vp.emplace_back(p,1); prev=p; } return vp; } inline static vector divisor_impl(const u64 n) { auto fac = factorization_impl(n); vector res = {1}; for(auto& [p,m]: fac) { u32 sz = res.size(); for(u32 i=0;i> factorization(const u64 n) {return factorization_impl(n);} //素因数が愚直に昇順で返却される inline static vector factor(const u64 n) {return move(factor(n, true));} //約数が昇順で列挙される inline static vector divisor(const u64 n) {return divisor_impl(n); } inline static constexpr long long gcd(long long n, long long m) { return (n>m ? pre(n,m) : pre(m,n));} inline static constexpr long long naive_gcd(long long a, long long b) { return (b ? naive_gcd(b, a % b):a);} inline static constexpr long long lcm(long long a, long long b) {return (a*b ? (a / gcd(a, b)*b): 0);} inline static constexpr long long ext_gcd(long long a, long long b, long long &x, long long &y) { if (b == 0) return x = 1, y = 0, a; long long d = ext_gcd(b, a%b, y, x); return y -= a / b * x, d; } }; /** * @url * @est */ int main() { cin.tie(0);ios::sync_with_stdio(false); int N; read(N); vector A(N),dp(300001,0); for(int i = 0; i < N; ++i) read(A[i]); for(int i = 0; i < N; ++i) { auto D = Prime::divisor(A[i]); if(A[i]!=0){ chmax(dp[A[i]],dp[0]+1); } for(auto e:D){ if(e==A[i]) continue; chmax(dp[A[i]],dp[e]+1); } } cout << *max_element(ALL(dp)) << endl; return 0; }