题目大意
求下列式子的值:
数据范围:$n \le 10^{30}$。
思路分析
Siyuan 太强啦 QwQ
先枚举 $\sqrt[3]i$ 的值:
考虑子问题:
考虑计算绿色部分:
枚举 $\lfloor \sqrt[3]n \rfloor$ 的因数,递归计算 $\varphi$ 值即可。时间复杂度 $O(n^{\frac{1}{6}})$。
再考虑计算紫色部分。令 $m = \lfloor \sqrt[3]n \rfloor - 1$,得:
使用整除分块 + 杜教筛即可做到 $O(n^\frac{2}{9})$。
代码实现
1 |
|
2 |
|
3 | using namespace std; |
4 | |
5 | typedef __int128 lll; |
6 | typedef long long ll; |
7 | const int maxn = 2e7, maxk = 10, mod = 998244353; |
8 | lll n; |
9 | ll m, a[maxk + 3]; |
10 | int k, p[maxn + 3], phi[maxn + 3], iphi[maxn + 3], c, b[maxk + 3]; |
11 | map<ll, int> mp_phi, mp_iphi, mp_m; |
12 | |
13 | void scan_lll(lll &n) { |
14 | n = 0; |
15 | char ch = getchar(); |
16 | while (!isdigit(ch)) { |
17 | ch = getchar(); |
18 | } |
19 | while (isdigit(ch)) { |
20 | n = n * 10 + (ch ^ '0'); |
21 | ch = getchar(); |
22 | } |
23 | } |
24 | |
25 | void prework(int n) { |
26 | phi[1] = 1; |
27 | for (int i = 2; i <= n; i++) { |
28 | if (!phi[i]) { |
29 | phi[i] = i - 1; |
30 | p[++k] = i; |
31 | } |
32 | for (int j = 1; j <= k && i * p[j] <= n; j++) { |
33 | if (i % p[j] == 0) { |
34 | phi[i * p[j]] = phi[i] * p[j]; |
35 | break; |
36 | } |
37 | phi[i * p[j]] = phi[i] * (p[j] - 1); |
38 | } |
39 | } |
40 | for (int i = 1; i <= n; i++) { |
41 | iphi[i] = 1ll * phi[i] * i % mod; |
42 | } |
43 | for (int i = 2; i <= n; i++) { |
44 | phi[i] += phi[i - 1]; |
45 | phi[i] < mod ? 0 : phi[i] -= mod; |
46 | iphi[i] += iphi[i - 1]; |
47 | iphi[i] < mod ? 0 : iphi[i] -= mod; |
48 | } |
49 | } |
50 | |
51 | int sum_id(int n) { |
52 | return 1ll * n * (n + 1) / 2 % mod; |
53 | } |
54 | |
55 | int sum_sqr(int n) { |
56 | return (lll) n * (n + 1) * (2 * n + 1) / 6 % mod; |
57 | } |
58 | |
59 | int sum_phi(ll n) { |
60 | if (n <= maxn) { |
61 | return phi[n]; |
62 | } |
63 | if (mp_phi.count(n)) { |
64 | return mp_phi[n]; |
65 | } |
66 | int &x = mp_phi[n] = sum_id(n % mod); |
67 | for (ll i = 2, j = i; i <= n; i = j + 1, j = i) { |
68 | j = n / (n / i); |
69 | x = (x + (j - i + 1) % mod * (mod - sum_phi(n / i))) % mod; |
70 | } |
71 | return x; |
72 | } |
73 | |
74 | int sum_iphi(ll n) { |
75 | if (n <= maxn) { |
76 | return iphi[n]; |
77 | } |
78 | if (mp_iphi.count(n)) { |
79 | return mp_iphi[n]; |
80 | } |
81 | int &x = mp_iphi[n] = sum_sqr(n % mod); |
82 | for (ll i = 2, j = i; i <= n; i = j + 1, j = i) { |
83 | j = n / (n / i); |
84 | x = (x + 1ll * (sum_id(j % mod) - sum_id((i - 1) % mod) + mod) * (mod - sum_iphi(n / i))) % mod; |
85 | } |
86 | return x; |
87 | } |
88 | |
89 | int dfs(int &ans, ll m, lll n, int b[]) { |
90 | if (mp_m.count(m)) { |
91 | return mp_m[m]; |
92 | } |
93 | int &res = mp_m[m] = 0; |
94 | if (m == 1) { |
95 | ans = (ans + n) % mod; |
96 | return res = 1; |
97 | } |
98 | int t[maxk + 3]; |
99 | for (int i = 1; i <= c; i++) { |
100 | t[i] = b[i]; |
101 | } |
102 | for (int i = 1; i <= c; i++) { |
103 | if (b[i] > 0) { |
104 | t[i]--; |
105 | dfs(ans, m / a[i], n, t); |
106 | t[i]++; |
107 | } |
108 | } |
109 | for (int i = 1; i <= c; i++) { |
110 | if (b[i] > 0) { |
111 | t[i]--; |
112 | res = 1ll * dfs(ans, m / a[i], n, t) * (a[i] - !t[i]) % mod; |
113 | ans = (ans + (n / m) % mod * res) % mod; |
114 | break; |
115 | } |
116 | } |
117 | return res; |
118 | } |
119 | |
120 | int solve_1(lll n, ll m) { |
121 | int ans = m % mod; |
122 | c = 0; |
123 | ll t = m; |
124 | for (int i = 2; 1ll * i * i <= t; i++) { |
125 | if (t % i == 0) { |
126 | a[++c] = i; |
127 | while (t % i == 0) { |
128 | t /= i, b[c]++; |
129 | } |
130 | } |
131 | } |
132 | if (t > 1) { |
133 | a[++c] = t, b[c] = 1; |
134 | } |
135 | dfs(ans, m, n, b); |
136 | return ans; |
137 | } |
138 | |
139 | int solve_2(ll n) { |
140 | int ans = sum_id(n % mod); |
141 | for (ll i = 1, j = i; i <= n; i = j + 1, j = i) { |
142 | j = n / (n / i); |
143 | ans = (ans + 3ll * (sum_phi(j) - sum_phi(i - 1) + mod) * sum_id(n / i % mod)) % mod; |
144 | ans = (ans + 3ll * (sum_iphi(j) - sum_iphi(i - 1) + mod) * sum_sqr(n / i % mod)) % mod; |
145 | } |
146 | return ans; |
147 | } |
148 | |
149 | int main() { |
150 | scan_lll(n); |
151 | m = powl(n, 1. / 3); |
152 | while ((lll) (m + 1) * (m + 1) * (m + 1) <= n) { |
153 | m++; |
154 | } |
155 | prework(min(1ll * maxn, m)); |
156 | printf("%d\n", (solve_1(n - (lll) m * m * m, m) + solve_2(m - 1)) % mod); |
157 | return 0; |
158 | } |