版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/89762837
【题目链接】
【思路要点】
- 给出结论:
定义函数 ,满足
令 ,其中 均为质数, 均为正整数。那么有- 因此 除去 后为积性函数,使用传统的积性函数求和即可。
- 关于结论的证明可以参考笔者 年的国家集训队论文。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1e6 + 5; const int MAXLOG = 256; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } ll n, k, val[MAXN], cnt[MAXN][2]; int m, P, k3, home1[MAXN], home2[MAXN]; int limit, tot, tpow[MAXN], prime[MAXN], pre[MAXN][2]; void update(int &x, int y) { x += y; if (x >= P) x -= P; } int power(int x, ll y) { if (y == 0) return 1; int tmp = power(x, y / 2); if (y % 2 == 0) return 1ll * tmp * tmp % P; else return 1ll * tmp * tmp % P * x % P; } int solve(ll x, int y) { if (x <= 1 || prime[y] > x) return 0; int ans = 0, pos = 0; if (x <= limit) pos = home1[x]; else pos = home2[n / x]; ans = ((cnt[pos][1] - pre[y - 1][1]) + (cnt[pos][0] - pre[y - 1][0]) % P * tpow[3]) % P; if (prime[y] == 2) update(ans, 1); for (int i = y; i <= tot && 1ll * prime[i] * prime[i] <= x; i++) { ll now = prime[i], nxt = 1ll * prime[i] * prime[i]; for (int j = 1; nxt <= x; j++, now *= prime[i], nxt *= prime[i]) { if (prime[i] % 4 == 1) update(ans, (1ll * tpow[2 * j + 1] * solve(x / now, i + 1) + tpow[2 * j + 3]) % P); else update(ans, (solve(x / now, i + 1) + 1) % P); } } return ans; } void sieve(int n) { static int f[MAXN]; for (int i = 2; i <= n; i++) { if (f[i] == 0) prime[++tot] = f[i] = i; for (int j = 1; j <= tot && prime[j] <= f[i]; j++) { int tmp = prime[j] * i; if (tmp > n) break; f[tmp] = prime[j]; } } for (int i = 1; i <= tot; i++) { pre[i][0] = pre[i - 1][0]; pre[i][1] = pre[i - 1][1]; if (prime[i] % 4 == 1) pre[i][0]++; if (prime[i] % 4 == 3) pre[i][1]++; } } int main() { read(n), read(k), read(P); sieve(limit = sqrt(n) + 5); for (ll i = 1, nxt; i <= n; i = nxt + 1) { ll tmp = n / i; val[++m] = tmp; if (tmp <= limit) home1[tmp] = m; else home2[n / tmp] = m; nxt = n / val[m]; cnt[m][0] = (tmp - 1) / 4; cnt[m][1] = (tmp + 1) / 4; } for (int i = 2; i <= tot; i++) for (int j = 1; 1ll * prime[i] * prime[i] <= val[j]; j++) { ll tmp = val[j] / prime[i]; int pos = 0; if (tmp <= limit) pos = home1[tmp]; else pos = home2[n / tmp]; if (prime[i] % 4 == 1) { cnt[j][0] -= cnt[pos][0] - (pre[i][0] - 1); cnt[j][1] -= cnt[pos][1] - pre[i][1]; } else { cnt[j][0] -= cnt[pos][1] - (pre[i][1] - 1); cnt[j][1] -= cnt[pos][0] - pre[i][0]; } } for (int i = 1; i <= MAXLOG; i++) tpow[i] = power(i, k); writeln(1ll * tpow[4] * (solve(n, 1) + 1) % P); return 0; }