結果
問題 |
No.2075 GCD Subsequence
|
ユーザー |
![]() |
提出日時 | 2025-03-25 15:44:17 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 408 ms / 4,000 ms |
コード長 | 2,410 bytes |
コンパイル時間 | 3,863 ms |
コンパイル使用メモリ | 286,740 KB |
実行使用メモリ | 19,656 KB |
最終ジャッジ日時 | 2025-03-25 15:44:30 |
合計ジャッジ時間 | 13,006 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 28 |
ソースコード
#include <bits/stdc++.h> #include <atcoder/modint> using namespace std; using namespace atcoder; using ll = long long; using mint = modint998244353; vector<int> spf; map<int, int> prime; void osa_k(int n){ spf.resize(n+1); for (int i=0; i<=n; i++) spf[i] = i; for (int i=2; i*i<=n; i++){ if (spf[i] == i){ for (int j=2; i*j <= n; j++){ spf[i*j] = min(spf[i*j], i); } } } } void prime_factor(int n){ prime.clear(); while(n != 1){ prime[spf[n]]++; n /= spf[n]; } } //O(D(n)+log(n)) vector<int> all_factor(int n){ vector<int> res={1}; prime_factor(n); for (auto [p, e] : prime){ int x=1, m=res.size(); for (int j=0; j<e; j++){ x *= p; for (int k=0; k<m; k++) res.push_back(res[k] * x); } } return res; } int main(){ cin.tie(nullptr); ios_base::sync_with_stdio(false); /* dp(i)=末尾の要素がiとなるものの数 dp(A)+=1 dp(A)+=dp(k) (gcd(A, k)>1) sm(i)=dp(i*k)の総和 sm(2) = dp(2)+dp(4)+dp(6)+dp(8)+dp(10)+dp(12) sm(3) = dp(3)+dp(6)+dp(9)+dp(12) sm(6) = dp(6)+dp(12) dp(6) += sm(2)+sm(3)-sm(6) dp(8) += sm(2) dp(12) += sm(2)+sm(3)-sm(6) Aを素因数だけにしておく。(指数が2以上のものは意味がない。) dp(A)+= smの包除原理 sm(i)+=dp(A)-(前のdp(A)) (i|A) */ int N,M=1e6; osa_k(M); cin >> N; vector<int> A(N); for (int i=0; i<N; i++){ cin >> A[i]; prime_factor(A[i]); int z=1; for (auto [x, y] : prime) z *= x; A[i] = z; } vector<int> p(M+1); //素因数の数 for (int i=2; i<=M; i++){ int j=i; while(j!=1){ p[i]++; j /= spf[j]; } } mint ans=0, prv=0, nxt=0; vector<mint> dp(M+1), sm(M+1); for (int i=0; i<N; i++){ if (A[i] == 1){ ans++; continue; } prv = dp[A[i]]; vector<int> factors = all_factor(A[i]); for (auto x : factors) if (x > 1) dp[A[i]] += sm[x] * (p[x] % 2 == 0 ? -1 : 1); dp[A[i]]++; nxt = dp[A[i]]; for (auto x : factors) if (x > 1) sm[x] += nxt-prv; } for (int i=2; i<=M; i++) ans += dp[i]; cout << ans.val() << endl; return 0; }