LG P6156 簡單題
阿新 • • 發佈:2021-07-20
\(\text{Problem}\)
\(\text{Analysis}\)
顯然 \(f=\mu^2\)
那麼
我們考慮預處理
這樣就可以數論分快套數論分快搞定
那麼就考慮如何預處理這三個字首和
顯然 \(g(d)=d^k\) 是個積性函式,於是可以線篩處理處所有 \(d^k\)
那 \(f_1\) 和 \(f_2\) 一遍就出來了
現在就看 \(f_3\) 了
我們對 \(f_3\) 差分
也就是說我們處理出 \(\sum_{i=1}^{2n} d^k\)
然後再做一遍字首和就可以得到 \(f_3\)
到此本題就結束了
注意空間!!
\(\text{Code}\)
#include<cstdio> #include<iostream> #define re register using namespace std; typedef long long LL; const int N = 1e7, P = 998244353; LL k; int totp, n; int pr[N], vis[N + 5], mu[N + 5], pk[N + 5], spk[N + 5], f1[N / 2 + 5], f2[N / 2 + 5], f3[N / 2 + 5]; inline int fpow(LL x, LL y) { LL res = 1; for(; y; y >>= 1) { if (y & 1) res = res * x % P; x = x * x % P; } return res; } inline void Euler() { vis[1] = mu[1] = pk[1] = 1; for(re int i = 2; i <= N; i++) { if (!vis[i]) pr[++totp] = i, mu[i] = -1, pk[i] = fpow(i, k); for(re int j = 1; j <= totp && i * pr[j] <= N; j++) { vis[i * pr[j]] = 1, pk[i * pr[j]] = (LL)pk[i] * pk[pr[j]] % P; if (!(i % pr[j])) break; mu[i * pr[j]] = -mu[i]; } } for(re int i = 1; i <= N / 2; i++) f1[i] = ((LL)f1[i - 1] + (LL)pk[i] * i % P * mu[i] * mu[i]) % P, f2[i] = ((LL)f2[i - 1] + (LL)pk[i] * mu[i] + P) % P; for(re int i = 1; i <= N; i++) spk[i] = (pk[i] + spk[i - 1]) % P; for(re int i = 1; i <= N / 2; i++) f3[i] = ((LL)f3[i - 1] + 2LL * (spk[2 * i] - spk[i] + P) % P - pk[2 * i] % P + P) % P; } inline int query(int n) { LL res = 0; for(re int l = 1, r; l <= n; l = r + 1) { r = n / (n / l); res = (res + (LL)(f2[r] - f2[l - 1] + P) % P * f3[n / l] % P) % P; } return res; } int main() { scanf("%d%lld", &n, &k); Euler(); LL ans = 0; for(re int l = 1, r; l <= n; l = r + 1) { r = n / (n / l); ans = (ans + (LL)(f1[r] - f1[l - 1] + P) % P * query(n / l)) % P; } printf("%lld\n", ans); }