CCFCAT2025 简单的数学题
若 \(n = p_1^{k_1}p_2^{k_2}\cdots p_r^{k_r}\),则有 \(f(n) = k_1^{p_1}k_2^{p_2}\cdots k_r^{p_r}\).
求 \(\sum\limits_{i = 1}^{n} f(n)\).(\(n \le 10^{13}\))
这个题目需要用到 PN 筛,容易观察到 \(f(p) = g(p) = 1\),此时满足 \(h(p) = 0\),那么我们不妨考虑 \(g\) 函数恒等于 \(1\),那么由于 \(f(p^k)\) 是好求的,所以我们可以简单得到:
\[g(1)h(p^k) = f(p^k) - g(p)h(p^{k - 1}) - \cdots - g(p^{k})h(1)
\]
容易看出:
\[h(p^k) = f(p^k) - \sum_{i = 0}^{k - 1}h(p^i)
\]
通过前缀和容易得出 \(h\) 在质数的幂处的取值,由于 \(g\) 的前缀和是好求的,因此我们可以利用 PN 筛在 \(O(\sqrt{n})\) 的复杂度求出 \(f(n)\) 的前缀和。其中复杂度最高在 \(h(n)\) 的求解,其复杂度为 \(O(\sqrt{n}\log{n})\)。
小心 PN 筛边界会爆 long long。
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define i128 __int128
#define ld long double
#define pb push_back
#define PII pair<ll, ll>
#define PPI pair<ll, PII>
#define vi vector<ll>
#define vvi vector<vector<ll>>
#define clr(f, n) memset(f, 0, sizeof(int) * (n))
#define cpy(f, g, n) memcpy(f, g, sizeof(int) * (n))
#define rev(f, n) reverse(f, f + (n))
const int N = 3.5e6 + 10, mod = 998244353;
int primes[N], cnt, st[N];
ll n, maxn, ans;
unordered_map<ll, ll> h[N];
// for all g[i] = 1
ll qpow(ll a, ll k = mod - 2) {
ll res = 1;
while (k) {
if (k & 1) res = res * a % mod;
k >>= 1;
a = a * a % mod;
}
return res;
}
void dfs_PN(int idx, ll now, ll val) {
(ans += (n / now) % mod * val) %= mod;
if (idx >= cnt || now > n / primes[idx] / primes[idx]) return;
for (int i = idx; i < cnt; i ++ ) {
if (now > n / primes[i] / primes[i]) break;
ll x = now * primes[i];
for (int j = 2; x <= n / primes[i]; j ++ ) {
x *= primes[i];
if (!h[i].count(j)) h[i][j] = (qpow(j, primes[i]) - qpow(j - 1, primes[i]) + mod) % mod;
if (h[i][j]) dfs_PN(i + 1, x, h[i][j] * val % mod);
}
}
}
void solve() {
cin >> n, maxn = sqrt(n) + 1;
for (int i = 2; i < maxn; i ++ ) {
if (!st[i]) primes[cnt ++ ] = i;
for (int j = 0; i * primes[j] < maxn; j ++ ) {
st[i * primes[j]] = 1;
if (i % primes[j] == 0) break;
}
}
dfs_PN(0, 1, 1);
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int T = 1;
// cin >> T;
while (T -- ) solve();
return 0;
}

浙公网安备 33010602011771号