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;
}
posted @ 2023-08-28 10:36  johnsmith0x3f  阅读(12)  评论(0)    收藏  举报