The Sum of Unitary Totient
积性函数,满足质数点是多项式,直接 min_25 了,由于单次求解,所以使用递归的 min_25 会较快。
#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10;int prime[N], a[N], id1[N], id2[N], cnt, n, T, m;long long sum1[N], sum2[N], g1[N], g2[N], s[N];bool st[N];inline int ID(int x) {return x <= T ? id1[x] : id2[n / x];
}void init() {T = sqrt(n + 0.5);m = 0;for (int l = 1, r; l <= n; l = r + 1) {r = n / (n / l);a[++m] = n / l;a[m] <= T ? id1[a[m]] = m : id2[n / a[m]] = m;g1[m] = 1ll * a[m] * (a[m] + 1) / 2 - 1;g2[m] = a[m] - 1;}for (int j = 1; j <= cnt && 1ll * prime[j] * prime[j] <= n; j++) {for (int i = 1; i <= m && 1ll * prime[j] * prime[j] <= a[i]; i++) {g1[i] -= 1ll * prime[j] * (g1[ID(a[i] / prime[j])] - sum1[j - 1]);g2[i] -= (g2[ID(a[i] / prime[j])] - sum2[j - 1]);}}/*下面是递推的 min_25。*/// for (int i = 1; i <= m; i++) {// s[i] = g1[i] - g2[i];// }// int top = 1;// while (1ll * prime[top] * prime[top] <= n) {// top++;// }// top--;// for (int j = top; j >= 1; j--) {// for (int i = 1; i <= m && 1ll * prime[j] * prime[j] <= a[i]; i++) {// for (int cur = prime[j]; 1ll * cur * prime[j] <= a[i]; cur *= prime[j]) {// s[i] += 1ll * (cur - 1) * (s[ID(a[i] / cur)] - sum1[j] + sum2[j]) + cur * prime[j] - 1;// }// }// }
}long long solve(int n, int m) {if (n < prime[m]) {return 0;} long long res = g1[ID(n)] - g2[ID(n)] - sum1[m - 1] + sum2[m - 1];for(int j = m; j <= cnt && 1ll * prime[j] * prime[j] <= n; j++) {for(int i = prime[j]; 1ll * i * prime[j] <= n; i *= prime[j]) {res += (i - 1) * solve(n / i, j + 1) + i * prime[j] - 1;}} return res;
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);for (int i = 2; i < N; i++) {if (!st[i]) {prime[++cnt] = i;sum1[cnt] = sum1[cnt - 1] + i;sum2[cnt] = sum2[cnt - 1] + 1;}for (int j = 1; j <= cnt && 1ll * i * prime[j] < N; j++) {st[i * prime[j]] = 1;if (i % prime[j] == 0) {break;}}}while (scanf("%d", &n) != EOF) {init();printf("%lld\n", solve(n, 1) + 1);}return 0;
}