只要你跑的够快,锅就追不上你

0%

「LOJ 6686」Stupid GCD(数论)

题目大意

「LOJ 6686」Stupid GCD

求下列式子的值:

数据范围:$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
#include <bits/stdc++.h>
2
#define debug(...) fprintf(stderr, __VA_ARGS__)
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
}