题意
首先是套路的化式子为枚举gcd:
我们设,莫比乌斯反演可得:
又因为很好算,等于,那么代入原式:
我们想把那个移出来,因为这个东西可以整除分块算,那么我们改枚举倍数为枚举约数:
我们想起来莫比乌斯函数有一个性质:
两边同时乘上,那么:
我们发现这个式子和答案后面那个式子是一样的,那么:
我们用杜教筛算欧拉函数的前缀和整除分块做就好了,复杂度。
#include <bits/stdc++.h>
#define pb push_back
#define ll long long
#define For(i, a, b) for (int i = a; i <= b; ++ i)
using namespace std;
const int N = 2e6;
const int mod = 1e9 + 7;
vector<int> Prime;
bitset<N + 3> Notp;
unordered_map<ll, int> SPhi;
int Phi[N + 3], Sphi[N + 3];
int Mul(int x, int y) { return 1ll * x * y % mod; }
int Add(int x, int y) { return (x += y) < mod ? x : x - mod; }
void Get_Prime() {
Notp[0] = Notp[1] = Phi[1] = 1;
For(i, 2, N) {
if (!Notp[i]) Prime.pb(i), Phi[i] = i - 1;
for (auto P : Prime) {
if (P * i > N) break;
Notp[P * i] = 1;
if (!(i % P)) {
Phi[P * i] = Mul(Phi[i], P);
break;
}
Phi[P * i] = Mul(Phi[i], P - 1);
}
}
For(i, 1, N) Sphi[i] = Add(Sphi[i - 1], Phi[i]);
}
int Query_Phi(ll n) {
if (n <= N) return Sphi[n];
if (SPhi[n]) return SPhi[n];
int res = ((n % mod) * (n % mod + 1)) % mod * (mod + 1) / 2 % mod;
for (ll l = 2, r; l <= n; l = r + 1) {
r = n / (n / l);
res = Add(res, mod - 1ll * Query_Phi(n / l) * (r - l + 1) % mod);
}
return SPhi[n] = res;
}
int main() {
ll n, ans = 0;
Get_Prime();
cin >> n;
for (ll l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
ans += 1ll * Mul(n / l % mod, n / l % mod) * (Query_Phi(r) - Query_Phi(l - 1)) % mod;
}
printf("%lld\n", (ans % mod + mod) % mod);
return 0;
}