这里
题意:说白了就是求这个
∑
i
=
1
n
p
s
m
a
x
(
i
)
\sum_{i=1}^{n}p_{smax}(i)
∑i=1npsmax(i)
其中
p
s
m
a
x
p_{smax}
psmax表示次小质因子,规定1和质数的次小质因子为0
做法:这道题是一道min25筛法的题,但不过不是普通的积性函数求和,需要对该算法有一定的理解。
首先我们还是以
s
(
n
,
j
)
s(n,j)
s(n,j)表示在
1
−
n
1-n
1−n范围内最小质因子不小于
p
j
p_j
pj的和。
对于质数部分没有贡献为0,对于合数部分我们枚举最小质因子
p
j
p_j
pj的幂次,那么合数分为两部分,一部分
p
j
k
p
l
(
l
>
j
)
,
p
j
k
x
p_{j}^{k}p_{l}(l>j),p_{j}^{k}x
pjkpl(l>j),pjkx,这两部分中前一部分的答案为
p
j
p_{j}
pj,后一部分的答案
x
x
x这个合数的答案,因此
s
(
n
,
j
)
=
∑
k
=
j
∣
p
∣
∑
e
=
1
n
(
s
(
n
/
p
j
k
,
k
+
1
)
+
p
k
∑
x
=
p
k
n
i
s
p
r
i
m
e
)
s(n,j) = \sum_{k=j}^{|p|}\sum_{e=1}^{n} (s(n/p_{j}^{k},k+1)+p_{k}\sum_{x=p_{k}}^{n}isprime)
s(n,j)=∑k=j∣p∣∑e=1n(s(n/pjk,k+1)+pk∑x=pknisprime)
后面关于质数的计数部分,直接
g
g
g函数的处理即可。
听它们说还可以有另外一种写法就是强制第y层的质数为最大质因子,这样递推,我也没有这样写过,但不过估计比这个复杂。
#include "bits/stdc++.h"
using namespace std;
inline int read() {
int x = 0;
bool f = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = 0;
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
if (f) return x;
return 0 - x;
}
typedef long long ll;
const int maxn = 400010;
const ll mod = 1000000000 + 7;
ll quick(ll a, ll n, ll p) {
ll ans = 1;
for (; n; n >>= 1, a = a * a % p)
if (n & 1) ans = ans * a % p;
return ans;
}
int vis[maxn], sqr, cnt = 0;
ll suf1[maxn], suf2[maxn], inv2, inv6, n, pri[maxn];
void init(int lim) {
vis[1] = 1;
for (int i = 2; i <= lim; i++) {
if (!vis[i]) {
pri[++cnt] = i;
}
for (int j = 1; j <= cnt && i * pri[j] <= lim; j++) {
vis[i * pri[j]] = 1;
if (i % pri[j] == 0) break;
}
}
}
int id1[maxn], id2[maxn], m = 0;
ll w[maxn << 1], g[maxn << 1], h[maxn << 1];
int getid(ll x) {
if (x <= sqr) return id1[x];
return id2[n / x];
}
void calc1() {
for (ll l = 1, r; l <= n; l = r + 1) {
r = n / (n / l);
w[++m] = n / l;
g[m] = w[m] - 1;
if (w[m] <= sqr) id1[w[m]] = m;
else id2[r] = m;
}
for (int j = 1; j <= cnt; j++) {
for (int i = 1; i <= m && pri[j] * pri[j] <= w[i]; i++) {
int k = getid(w[i] / pri[j]);
g[i] -= g[k] - j + 1;
}
}
}
ll sum(ll x, int y) {
if (x <= 1 || pri[y] > x) return 0;
int k = getid(x);
ll ret = 0;
for (int i = y; i <= cnt && 1ll * pri[i] * pri[i] <= x; i++) {
ll t1 = pri[i], t2 = 1ll * pri[i] * pri[i];
for (int e = 1; t2 <= x; ++e, t1 = t2, t2 *= pri[i]) {
ret += (sum(x / t1, i + 1) + 1ll * pri[i] * (g[getid(x / t1)] - i + 1));
}
}
return ret;
}
int main() {
// inv2 = quick(2, mod - 2, mod);
// inv6 = quick(6, mod - 2, mod);
ll l, r;
cin >> l >> r;
n = r;
sqr = sqrt(n);
init(sqr);
calc1();
ll ans = sum(n, 1);
n = l - 1;
sqr = sqrt(n);
m = 0;
calc1();
ans = ans - sum(n, 1);
cout << ans << endl;
return 0;
}