【题解】Luogu-P6156 简单题
P6156 简单题 和 P6222 「P6156 简单题」加强版
加强版卡空间。
Description
-
给定整数 \(n, k\),请求出
\[\left[\sum_{i = 1}^n \sum_{j = 1}^n (i + j)^k f(\gcd(i, j)) \gcd(i, j) \right] \bmod 998244353 \]\[f(n) = \begin{cases} 0 & \exists d > 1, d^2\mid n \\ 1 & \text{othervise} \end{cases} \] -
\(1\le n\le 5\times 10^6, 1\le k\le 10^{18}\)。
Solution
一个重要的性质:\(f(n) = \mu^2(n)\)。
把后面那一项拎出来看
设
则
整除分块即可。
观察到题目中
时间调至 \(1s\),卡掉了 \(\Omicron(n\log k), \Omicron(n\log p)\) 的做法。
乱杀 /fad
于是预处理要做到 \(\Omicron(n)\)。
首先是 \(n^k\),其实就是 \(\operatorname{Id}_k(n)\),这是一个完全积性函数,可以线性筛;对于质数暴力计算是 \(\Omicron(\log p\cdot \pi(n)) \simeq \Omicron(n)\),是线性的;我们顺便求出它的前缀和,记作 \(g(n) = \sum_{i = 1}^n i^k\)。
然后是 \(f(n)\),令 \(h(n) = \sum_{i = 1}^n g(i)\)。
结论:
\[f(n) = h(2n) - 2h(n) \]
证明:
数学归纳法。
\(f(1) = \sum_{i = 1}^n\sum_{j = 1}^n (i + j)^k = 1\)
当 \(f(n) = h(2n) + 2h(n)\) 成立时,有
\[\begin{aligned} f(n + 1) & = \sum_{i = 1}^n \sum_{j = 1}^n (i + j)^k \\ & = f(n) + 2 \sum_{i = 1}^n (i + n + 1)^k + (2n + 2)^k \\ & = f(n) + 2 \sum_{i = n + 2}^{2n +1} i^k + \sum_{i = 2n + 2}^{2n + 2} i^k \\ & = h(2n) - 2h(n) + 2[g(2n +1) - g(n + 1)] + [g(2n + 2) - g(2n + 1)] \\ & = \sum_{i = 1}^{2n} g(i) - 2 \sum_{i = 1}^n g(i) + 2 g(2n + 1) - 2 g(n + 1) + g(2n + 2) - g(2n + 1) \\ & = \left(\sum_{i = 1}^{2n} g(i) + g(2n + 1) + g(2n + 2) \right) - 2 \left(\sum_{i = 1}^n g(i) + g(n + 1) \right) \\ & = h(2n + 2) - 2h(n + 1) \end{aligned} \]证毕。
所以 \(f(n)\) 可以 \(\Theta(1)\) 求。
最后是
所以这玩意也是个积性函数,考虑线性筛。
-
\(i\in \mathbb{P}\):\(\alpha(i) = 1\cdot \mu^2(1) \cdot \mu(i) + i\cdot \mu^2(i) \cdot \mu(1) = i- 1\);
-
\(p_j\nmid i\):\(\alpha(i\cdot p_j) = \alpha(i) \cdot \alpha(p_j)\);
-
\(p_j\mid i\):设 \(i\) 含 \(k\) 个质因数 \(p_j\),有 \(\alpha(i\cdot p_j) = \alpha\left(\dfrac{i}{p_j^k} \cdot (p_j\cdot p_j^k) \right) = \alpha\left(\dfrac{i}{p_j^k} \right) \cdot \alpha(p_j^{k +1})\) 。
现在考虑 \(\alpha(p^k)(k\ge 2)\) 的取值:
- 若 \(k = 2\),则 \(\alpha(p^2) = 1\cdot \mu^2(1) \cdot \mu(p^2) + p\cdot \mu^2(p) \cdot \mu(p) + p^2\cdot \mu^2(p^2) \cdot \mu(1) = -p\);
- 若 \(k\ge 3\),则根据抽屉原理,\(d\) 和 \(\dfrac{n}{d}\) 中必有一个含有至少 \(2\) 个质因数 \(p\),\(\mu\) 值为 \(0\),此时 \(\alpha(p^k) = 0\)。
Code
// 18 = 9 + 9 = 18.
#include <iostream>
#include <cstdio>
#define Debug(x) cout << #x << "=" << x << endl;
typedef long long ll;
using namespace std;
const int MAXN = 1e7 + 5;
const int MOD = 998244353;
int qpow(int a, int b)
{
int base = a, ans = 1;
while (b)
{
if (b & 1)
{
ans = (ll)ans * base % MOD;
}
base = (ll)base * base % MOD;
b >>= 1;
}
return ans;
}
int p[MAXN], id[MAXN], alpha[MAXN], sum[MAXN];
bool vis[MAXN];
int g[MAXN], h[MAXN];
void pre(int n, int k)
{
id[1] = alpha[1] = 1;
for (int i = 2; i <= n; i++)
{
if (!vis[i])
{
p[++p[0]] = i;
id[i] = qpow(i, k);
alpha[i] = i - 1;
}
for (int j = 1; j <= p[0] && i * p[j] <= n; j++)
{
vis[i * p[j]] = true;
id[i * p[j]] = (ll)id[i] * id[p[j]] % MOD;
if (i % p[j] == 0)
{
int k = i / p[j];
if (k % p[j] == 0)
{
alpha[i * p[j]] = 0;
}
else
{
alpha[i * p[j]] = (ll)alpha[k] * (MOD - p[j]) % MOD;
}
break;
}
alpha[i * p[j]] = (ll)alpha[i] * alpha[p[j]] % MOD;
}
}
for (int i = 1; i <= n; i++)
{
sum[i] = (sum[i - 1] + (ll)id[i] * alpha[i] % MOD) % MOD;
g[i] = (g[i - 1] + id[i]) % MOD;
h[i] = (h[i - 1] + g[i]) % MOD;
}
}
int f(int n)
{
return (h[2 * n] - (ll)2 * h[n] % MOD + MOD) % MOD;
}
int GetSum(int l, int r)
{
return (sum[r] - sum[l - 1] + MOD) % MOD;
}
int block(int n)
{
int res = 0;
for (int l = 1, r; l <= n; l = r + 1)
{
int k = n / l;
r = n / k;
res = (res + (ll)f(k) * GetSum(l, r) % MOD) % MOD;
}
return res;
}
int main()
{
int n;
ll k;
scanf("%d%lld", &n, &k);
pre(n * 2, k % (MOD - 1));
printf("%d\n", block(n));
return 0;
}