LuoguP2158 仪仗队
0x01
我们规定 \(\gcd(a, 0) = \gcd(0, a) = a\),则位置为 \((i, j) \ (0 \leqslant i, j < n)\) 的学生能被看到当且仅当 \(\gcd(i, j) = 1\).
故 \(\displaystyle ans = \sum_{i=0}^{n-1} \sum_{j=0}^{n-1} [\gcd(i, j) = 1]\).
0x02
则
\[\begin{aligned}
ans &= 3 + 2 \sum_{i=2}^{n-1} \sum_{j=1}^{i-1} [\gcd(i, j) = 1] \\
&= 3[n>1] + 2 \sum_{i=2}^{n-1} \varphi(i)
\end{aligned}
\]
或
\[\begin{aligned}
ans &= 2 + \sum_{i=1}^{n-1} \sum_{j=1}^{n-1} \sum \mu(d)[d | \! \gcd(i, j)] \\
&= \sum_{d=1}^{n-1} \mu(d) \cdot \lfloor \frac {n-1} d \rfloor^2
\end{aligned}
\]
0x03 Code
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0, f = 1; char c = getchar();
while(isdigit(c)^1) f &= c != 45, c = getchar();
while(isdigit(c)) x = (x<<1) + (x<<3) + (c^48), c = getchar();
return f ? x : -x;
}
int main() {
int n = read(), tot = 0;
vector<int> p(n+5, 0), phi(n+5, 0);
vector<bool> isp(n+5, 1);
for(int i = 2; i <= n; ++i) {
if(isp[i]) p[++tot] = i, phi[i] = i - 1;
for(int j = 1; j <= tot && i * p[j] <= n; ++j) {
isp[i * p[j]] = 0;
if(i % p[j]) phi[i * p[j]] = phi[i] * phi[p[j]];
else {
phi[i * p[j]] = phi[i] * p[j];
break;
}
}
}
int ans = n > 1 ? 3 : 0;
for(int i = 2; i < n; ++i) ans += 2 * phi[i];
printf("%d\n", ans);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
inline int read() {
int x = 0, f = 1; char c = getchar();
while(isdigit(c)^1) f &= c != 45, c = getchar();
while(isdigit(c)) x = (x<<1) + (x<<3) + (c^48), c = getchar();
return f ? x : -x;
}
inline int sqr(int x) {
return x * x;
}
int main() {
int n = read(), tot = 0;
vector<int> p(n+5, 0), mu(n+5, 0);
vector<bool> isp(n+5, 1);
mu[1] = 1;
for(int i = 2; i <= n; ++i) {
if(isp[i]) p[++tot] = i, mu[i] = -1;
for(int j = 1; j <= tot && i * p[j] <= n; ++j) {
isp[i * p[j]] = 0;
if(i % p[j]) mu[i * p[j]] = -mu[i];
else {
mu[i * p[j]] = 0;
break;
}
}
}
int ans = n > 1 ? 2 : 0;
for(int d = 1; d < n; ++d) ans += mu[d] * sqr((n-1) / d);
printf("%d\n", ans);
return 0;
}

浙公网安备 33010602011771号