【18徐州網路賽D】Easy Math
阿新 • • 發佈:2020-11-27
補充一點性質
\[\sum_{d|n}\varphi(d) = n \]證明:
對於 \(n = 1\) ,不難驗證滿足題意
對於 \(n = p^a\) ,
\[\sum_{d|n}\varphi(d) = 1 + \sum_{i = 1}^a\varphi(p^i) \\=p^a = n \]對於 \(n = p_1^{a_1}...p_k^{a_k}\)
\[\sum_{d|n}\varphi(d) = \sum_{i=0}^{a_1}\varphi(p_1^i)\sum_{i=0}^{a_2}\varphi(p_2^i)...\sum_{i=0}^{a_k}\varphi(p_k^i)\\=p_1^{a_1}...p_k^{a_k} = n \]- 若
i % p == 0
則 \(\varphi(i*p) = \varphi(i) * p\) , \(p\) 是質數
D. Easy Math
題意:
給定 \(m,n\) 求
\[\sum_{i=1}^m\mu(i * n) \]解:
這樣就可以進行遞迴了,但是我不會算複雜度...
還注意到一個地方,線篩的判斷 i % prime[j] == 0
的地方要注意函式的取值
#include<bits/stdc++.h> using namespace std; const int N = 1e6 + 10; typedef long long ll; ll prime[N], cnt, vis[N], mu[N], sum[N]; void init() { mu[1] = 1; for (int i = 2; i < N; i++) { if (!vis[i]) { prime[++cnt] = i; mu[i] = -1; } for (int j = 1; j <= cnt and prime[j] * i < N; j++) { vis[prime[j] * i] = 1; mu[prime[j] * i] = -mu[i]; if (i % prime[j] == 0) { //**這一行不能去掉** mu[i * prime[j]] = 0; break; } } } for (int i = 1; i < N; i++) sum[i] = sum[i - 1] + mu[i]; } ll n, m; unordered_map<ll, ll> M; ll djs(ll n) { if (n < N) return sum[n]; if (M.count(n)) return M[n]; ll ans = 1; for (ll l = 2, r; l <= n; l = r + 1) { r = n / (n / l); ans -= (r - l + 1) * djs(n / l); } return M[n] = ans; } ll cal(ll n) { int ans = 1; if (n < N) return mu[n]; for (ll i = 2; i * i <= n;i++) { if (n % i == 0) { if (n % (i * i) == 0) return 0; ans *= -1; n /= i; } } if (n > 1) ans *= -1; return ans; } ll solve(ll m, ll n) { if (n == 1) return djs(m); ll v = cal(n); if (v == 0) return 0; ll ans = 0; ll t = m < sqrt(n) ? m : sqrt(n); for (ll d = 1; d <= t; d++) { if (n % d == 0) { ans += cal(d) * solve(m / d, d); if (n / d <= m) ans += cal(n / d) * solve(m / (n / d), n / d); } } return v * ans; } int main() { init(); scanf("%lld%lld", &m, &n); printf("%lld\n", solve(m, n)); }