P2568 GCD是什么意思?

摘要:P2568 GCD 大意 求 (gcd(x, y) = p) 的个数。 思路 [text{Ans} = sum_{p le n} sum_{i=1}^{lfloor np rfloor} sum_{j=1}^{lf
P2568 GCD 大意 求 \(\gcd(x, y) = p\) 的个数。 思路 \[\text{Ans} = \sum_{p \le n} \sum_{i=1}^{\lfloor n/p \rfloor} \sum_{j=1}^{\lfloor n/p \rfloor} [\gcd(i, j) = 1] \] \[\text{Ans} = \sum_{p \le n} \sum_{d=1}^{\lfloor n/p \rfloor} \mu(d) \lfloor \frac{n}{pd} \rfloor^2 \] 令 \(T = pd\),通过更换求和次序: \[\text{Ans} = \sum_{T=1}^n \lfloor \frac{n}{T} \rfloor^2 \left( \sum_{p|T, p \in \text{prime}} \mu(\frac{T}{p}) \right) \] 代码 #include<iostream> using namespace std; const int MAXN = 1e7 + 5; bool vis[MAXN]; int mu[MAXN], f[MAXN]; int pr[MAXN], tot; long long sum[MAXN]; void init(int n){ mu[1] = 1; for(int i = 2;i <= n;i ++){ if(!vis[i]){ pr[++ tot] = i; mu[i] = -1; } for(int j = 1;pr[j] * i <= n && j <= tot;j ++){ vis[pr[j] * i] = 1; if(i % pr[j] == 0){ mu[pr[j] * i] = 0; break; } mu[pr[j] * i] = -mu[i]; } } for(int j = 1;j <= tot;j ++){ for(int i = 1;i * pr[j] <= n;i ++){ f[i * pr[j]] += mu[i]; } } for(int i = 1;i <= n;i ++){ sum[i] = sum[i - 1] + f[i]; } } void solve(){ int n, m; cin >> n; m = n; if(n > m) swap(n, m); long long ans = 0; for(int l = 1, r;l <= n;l = r + 1){ r = min(n / (n / l), m / (m / l)); ans += (long long)(n / l) * (m / l) * (sum[r] - sum[l - 1]); } cout << ans << '\n'; } int main(){ init(MAXN - 5); // int t; cin >> t; // while(t --){ solve(); // } return 0; }