题目传送
推公式博客传送

推完式子就是去朴素地求就行了Orz

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int m, mu[maxn], vis[maxn], primes[maxn], tot;
ll dp[maxn];
vector<int> factor[maxn];

ll ksm(ll a, ll b) {
    ll ret = 1;
    for (; b; b >>= 1) {
        if (b & 1)  ret = ret * a % mod;
        a = a * a % mod;
    }
    return ret;
}

void pre(int n) {
    rep(i, 1, n) {
        for (int k = 1; k * i <= n; k++)
            factor[k * i].push_back(i);
    }

    mu[1] = 1;
    rep(i, 2, n) {
        if (!vis[i]) {
            primes[tot++] = i;
            mu[i] = mod - 1;
        }
        for (int j = 0; j < tot && primes[j] * i <= n; j++) {
            vis[primes[j] * i] = 1;
            if (i % primes[j] == 0) break;
            mu[primes[j] * i] = mod - mu[i];
        }
    }
}

ll calc(int x, int d) {
    ll ret = 0;
    for (int i : factor[x / d]) {
        ret = (ret + (ll)mu[i] * (m / d / i) % mod) % mod;
    }
    return ret;
}

void DP() {
    dp[1] = 0;
    rep(i, 2, m) {
        ll k = m - m / i;
        ll tmp = m;
        for (auto j : factor[i]) {
            if (j == i) continue;
            tmp = (tmp + dp[j] * calc(i, j) % mod) % mod;
        }
        dp[i] = tmp * ksm(k, mod - 2) % mod;
    }
}

ll ANS(int m) {
    ll ret = 0;
    rep(i, 1, m) {
        ret = (ret + dp[i] + 1) % mod;
    }
    return ksm(m, mod - 2) * ret % mod;
}

int main() {
    read(m);
    pre(m);
    DP();
    writeln(ANS(m));
    return 0;
}
扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄