MIN25筛的瞎扯:
在复杂度
O
(
n
3
4
/
l
o
g
n
)
O(n^{\frac{3}{4}}/logn)
O(n43/logn)下解决一些积性函数的和
做一些规定:
p
r
i
m
e
(
i
)
:
i
为
质
数
时
,
为
一
,
否
则
为
0
prime(i):i为质数时,为一,否则为0
prime(i):i为质数时,为一,否则为0
p
k
:
p_k:
pk:表示第
k
k
k个质数,规定第零个质数为1;
m
i
n
p
(
i
)
:
表
示
i
的
最
小
质
因
子
minp(i):表示i的最小质因子
minp(i):表示i的最小质因子
g
(
n
,
j
)
=
∑
i
=
1
n
[
p
r
i
m
e
(
i
)
o
r
(
m
i
n
p
(
i
)
>
p
j
)
]
f
[
i
]
g(n,j)=\sum\limits_{i=1}^{n}[prime(i)or(minp(i)>p_j)]f[i]
g(n,j)=i=1∑n[prime(i)or(minp(i)>pj)]f[i]
S
(
n
,
j
)
=
∑
i
=
1
n
[
m
i
n
p
(
i
)
>
=
p
j
]
f
[
i
]
S(n,j)=\sum\limits_{i=1}^{n}[minp(i)>=p_j]f[i]
S(n,j)=i=1∑n[minp(i)>=pj]f[i]
p
p
p都是指质数
目的:求
∑
i
=
1
n
f
(
i
)
\sum\limits_{i=1}^nf(i)
i=1∑nf(i)
要求:
f
(
i
)
f(i)
f(i)是一个积性函数(即,
a
,
b
a,b
a,b互质时,
f
(
a
b
)
=
f
(
a
)
f
(
b
)
f(ab)=f(a)f(b)
f(ab)=f(a)f(b))
f
(
p
k
)
f(p^k)
f(pk)可以快速求
f
(
p
)
f(p)
f(p)是一个是一个关于
p
p
p的项数较少的多项式,或可以快速求值
令
f
(
p
)
=
c
1
p
k
1
+
c
2
p
k
2
+
⋯
f(p)=c_1p^{k_1}+c_2p^{k_2}+\cdots
f(p)=c1pk1+c2pk2+⋯
因为只要分别求出
p
k
p^k
pk的前
n
n
n项和,再与系数相乘,再把各项加起来就行
所以令
f
(
p
)
f(p)
f(p)=
p
k
p^k
pk
我们把问题简化为两部分来
第一部分
求解
∑
i
=
1
n
[
p
r
i
m
e
(
i
)
]
f
(
i
)
\sum\limits_{i=1}^{n}[prime(i)]f(i)
i=1∑n[prime(i)]f(i)
因为一个合数
a
a
a的最小质因子不大于
a
\sqrt{a}
a
所以
∑
i
=
1
n
[
p
r
i
m
e
(
i
)
]
f
(
i
)
=
g
(
n
,
∣
p
∣
)
\sum\limits_{i=1}^{n}[prime(i)]f(i)=g(n,|p|)
i=1∑n[prime(i)]f(i)=g(n,∣p∣),这里的|p|表示不大于
n
n
n的最大质数。
显然
g
(
n
,
0
)
=
∑
i
=
2
n
f
(
i
)
g(n,0)=\sum\limits_{i=2}^{n}f(i)
g(n,0)=i=2∑nf(i)
这一部分怎么办,我们最终要得到的是
∑
i
=
1
n
[
p
r
i
m
e
(
i
)
]
f
(
i
)
\sum\limits_{i=1}^{n}[prime(i)]f(i)
i=1∑n[prime(i)]f(i)所以我们在一部分假设对于任意
i
i
i,都有
f
(
i
)
=
i
k
f(i)=i^k
f(i)=ik,最后得到的是质数的
f
f
f值,所以并不会影响结果
现在来考虑怎么
g
(
n
,
j
−
1
)
转
移
到
g
(
n
,
j
)
g(n,j-1)转移到g(n,j)
g(n,j−1)转移到g(n,j)。
从
g
(
n
,
j
−
1
)
转
到
g
(
n
,
j
)
g(n,j-1)转到g(n,j)
g(n,j−1)转到g(n,j)会少掉一些合数的最小质因子是
p
j
p_j
pj的,所以要减掉。
若
p
j
⋅
p
j
>
n
p_j\cdot p_j>n
pj⋅pj>n则不存在这样的合数
此时有
g
(
n
,
j
)
=
g
(
n
,
j
−
1
)
g(n,j)=g(n,j-1)
g(n,j)=g(n,j−1)
那么
p
j
⋅
p
j
<
=
n
p_j\cdot p_j<=n
pj⋅pj<=n时
p
j
<
n
p
j
p_j<\frac{n}{p_j}
pj<pjn
所以
g
(
n
p
j
,
j
−
1
)
g(\frac{n}{p_j},j-1)
g(pjn,j−1)包含了小于
p
j
p_j
pj的质数和大于
p
j
p_j
pj且其最小质因子大于等于
p
j
p_j
pj的
f
f
f值
所以
g
(
n
p
j
,
j
−
1
)
−
g
(
p
j
,
j
−
1
)
g(\frac{n}{p_j},j-1)-g(p_j,j-1)
g(pjn,j−1)−g(pj,j−1)包含了最小质因子大于等于
p
j
p_j
pj的
f
f
f值。
所以有
g
(
n
,
j
)
=
g
(
n
,
j
−
1
)
−
f
(
p
j
)
(
g
(
n
p
j
−
g
(
p
j
,
j
−
1
)
g(n,j)=g(n,j-1)-f(p_j)(g(\frac{n}{p_j}-g(p_j,j-1)
g(n,j)=g(n,j−1)−f(pj)(g(pjn−g(pj,j−1)
第二部分
求解
S
(
n
,
1
)
S(n,1)
S(n,1) 则答案为
S
(
n
,
1
)
+
f
(
1
)
S(n,1)+f(1)
S(n,1)+f(1)
易知
S
(
n
,
m
)
=
0
S(n,m)=0
S(n,m)=0,
p
m
p_m
pm为大于
n
n
n的质数
第二部分其实道理跟第一部分一样的,自己推导一下就行。
结果:
S
(
n
,
j
)
=
g
(
n
,
∣
p
∣
)
−
∑
i
=
1
j
−
1
+
∑
k
=
j
p
k
2
<
=
n
∑
e
=
1
p
k
e
+
1
<
=
n
S
(
n
p
k
e
,
k
+
1
)
f
(
p
k
)
+
f
(
p
k
+
1
)
S(n,j)=g(n,|p|)-\sum\limits_{i=1}^{j-1}+\sum\limits_{k=j}^{p_k^2<=n}\sum\limits_{e=1}^{p_k^{e+1}<=n}S(\frac{n}{p_k^e},k+1)f(p_k)+f(p_{k+1})
S(n,j)=g(n,∣p∣)−i=1∑j−1+k=j∑pk2<=ne=1∑pke+1<=nS(pken,k+1)f(pk)+f(pk+1)
可以看到我们需要的
g
g
g点有
n
,
n
/
2
,
n
/
3
⋯
1
n,n/2,n/3\cdots 1
n,n/2,n/3⋯1一共
n
\sqrt{n}
n个点,所以需要一些分块
例题:简单的函数
#include<bits/stdc++.h>
#define ll long long
#define ull unsiged ll
#define rep(i, l, r) for (int i = l; i <= r; i++)
#define per(i, r, l) for (int i = r; i >= l; i--)
#define boots ios::sync_with_stdio(0); cin.tie(0)
#define endl '\n'
#define mod 1000000007
#define inf 0x3f3f3f3f
#define lnf LLONG_MAX
#define si(n) scanf("%d", &n)
#define sl(n) scanf("%lld", &n)
#define pf(n) printf("%lld\n", n)
#define sz size
using namespace std;
//const db pi = 3.1415926535898;
const int N = 2e5 + 10;
const int INV2 = 500000004;
int top;
unordered_map<ll, ll> mp;
int pri[N], ji[N];
ll g[N], h[N], pris[N];
ll w[N];
//pri[i]表示第几个质数,pris[i]表示前i个质数的和
void init(ll MX) {
memset(ji, 0, sizeof(ji));
pris[0] = 0;
top = 0;
for (int i = 2; i <= MX; i++) {
if (!ji[i]) {
pri[++top] = i;
pris[top] = (pris[top - 1] + i) % mod;
}
for (int j = 1; j <= top && 1ll * i * pri[j] <= MX; j++) {
int cur = i * pri[j];
ji[cur] = 1;
if (i % pri[j] == 0)
break;
}
}
}
void add(ll &a, ll b) {
a = (a + b) % mod;
if (a < 0)
a += mod;
return;
}
ll S(ll n, ll m) {
if (n <= 1 || pri[m] > n)
return 0;
ll kt = mp[n];
ll res = (g[kt] - h[kt] - (pris[m - 1] - m + 1)) % mod;
if (res < 0)
res += mod;
if (m == 1)
res += 2;
for (int k = m; k <= top && 1ll * pri[k] * pri[k] <= n; k++) {
ll ans = pri[k];
for (int i = 1; ans * pri[k] <= n; i++, ans *= pri[k]) {
add(res, (1ll * (S(n / ans, k + 1)) * (pri[k] ^ i) % mod + (pri[k] ^ (i + 1))) % mod);
}
}
return res;
}
int main() {
ll n;
while (cin >> n) {
ll fb = sqrt(n);
init(fb);
ll j;
int times = 0;
ll ans;
for (ll i = 1; i <= n; i = j + 1) {
w[++times] = n / i;
j = n / (n / i);
h[times] = (w[times] - 1) % mod;
g[times] = (((w[times] % mod * (w[times] + 1) % mod) % mod * INV2) % mod - 1 + mod) % mod;
mp[w[times]] = times;
}
for (int i = 1; i <= top; i++) {
ll k = 1ll * pri[i] * pri[i];
for (int j = 1; j <= times && k <= w[j]; j++) {
int kt = mp[w[j] / pri[i]];
add(g[j], mod - 1ll * pri[i] * (g[kt] - pris[i - 1]) % mod);
add(h[j], mod - (h[kt] - i + 1) % mod);
}
}
//g[i]-h[i]=w[i]以内
//w[i]表示n/i,mp[n/i]=i,h[i]表示n/i(含)内有多少个质数,g[i]=n/i内的质数之和表示
cout << (S(n, 1) + 1) % mod << endl;
}
}