# 2021牛客多校第六场G Hasse Diagram

$$H(i)$$的边数为$$f(i)$$

$f(i)=(e+1)f(i/p^e)+e\times d(i/p^e)$

$$f(x)$$$$d(x)$$均符合“在质数的次幂处可以快速求值“这一条件,并且$$d(x)$$是完全积性函数。但$$f(x)$$没有积性，不好搞。

$$f(p) = 1$$，可以取$$f(x)=1$$求其在质数处的前缀和（质数个数）（min_25的第一部分）

min_25的第二部分的递推式为

$S(i,j)=g(i,|P|)-g(p_j,|P|)+\sum_{k>j}\sum_{e=1}^{p_k^e\le n}f(p_k^e)(S(\lfloor\frac{i}{p_k^e}\rfloor,k)+[e>1])$

$f(i) = f(p^e)\times f(i/p^e)$

$S(i,j)=g(i,|P|)-g(p_j,|P|)+\sum_{k>j}\sum_{e=1}^{p_k^e\le n}( (e+1)S(\lfloor\frac{i}{p_k^e}\rfloor,k)+e(S_d(\lfloor\frac{i}{p^e_k}\rfloor,k)+[e>1])) \\ S_d(i,j)=2*(g(i,|P|)-g(p_j,|P|))+\sum_{k>j}\sum_{e=1}^{p_k^e\le n}d(p_k^e)(S_d(\lfloor\frac{i}{p_k^e}\rfloor,k)+[e>1])$

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 7;
#define ll long long
const ll md = 1145140019;
bool isp[maxn];
int tot, totw;
ll n, pri[maxn], idx1[maxn], idx2[maxn], T, w[maxn], g[maxn], sqrtn;
ll ksm(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1) res = res * a % md;
a = a * a % md;
b >>= 1;
}
return res;
}
void sieve() {
memset(isp, true, sizeof(isp));
isp[1] = false;
for (int i = 2; i <= 100000; i++) {
if (isp[i]) {
pri[++tot] = i;
}
for (int j = 1; j <= tot && i * pri[j] <= 100000; j++) {
isp[i*pri[j]] = 0;
if (i % pri[j] == 0) break;
}
}
}
typedef pair<ll, ll> pii;
pii S(ll i, ll j) {
if (pri[j] > i) return (pii){0,0};
int id = i > sqrtn ? idx2[n / i] : idx1[i];
ll sp = (g[id] - j + md) % md, d = 2ll * sp % md;
for (int k = j + 1; k <= tot && pri[k] * pri[k] <= i; k++) {
for (ll p = pri[k], e = 1; p <= i; p *= pri[k], e++) {
pii tmp = S(i / p, k);
d = (d + (tmp.second + (e > 1)) * (e + 1)/*d(pre[k]^e), 合数部分*/ % md) % md;
sp = (sp + (e+1)*tmp.first % md + e*(tmp.second + (e>1))%md)%md;
}
}
return (pii){sp, d};
}
int main() {
cin >> T;
sieve();
while (T--) {
cin >> n;
totw = 0;
sqrtn = sqrt(n);
for (ll l = 1, r; l <= n; l = r + 1) {
ll k = n / l;
r = n / k;
w[++totw] = k;
g[totw] = (k-1+md) % md;
if (k <= sqrtn) idx1[k] = totw;
else idx2[r] = totw;
}
for (int i = 1; i <= tot; i++) {
for (int j = 1; j <= totw && pri[i] * pri[i] <= w[j]; j++) {
ll k = w[j] / pri[i];
ll pre = k <= sqrtn ? idx1[k] : idx2[n/k];
g[j] = (g[j] - 1ll * (g[pre] - (i - 1) + md) % md + md) % md;
}
}
printf("%lld\n", S(n, 0).first);
}
}



update：整除分块的数有$$2\sqrt n$$个，要开2e5

posted @ 2021-08-12 15:09  yjmstr  阅读(97)  评论(0编辑  收藏  举报