f ( n ) = ∑ d ∣ n μ ( d ) 2 f(n) = \displaystyle\sum_{d|n}\mu(d)^2 f(n)=d∣n∑μ(d)2,根据 μ ( d ) \mu(d) μ(d) 的定义,当 d d d 的质因子的幂次不高于一次时有贡献,设 d d d 的质因子共有 w ( d ) w(d) w(d) 种, f ( n ) = ∑ d ∣ n μ ( d ) 2 = ∑ i = 0 w ( d ) C ( w ( d ) , i ) = 2 w ( d ) f(n) = \displaystyle\sum_{d|n}\mu(d)^2 = \sum_{i=0}^{w(d)}C(w(d),i)=2^{w(d)} f(n)=d∣n∑μ(d)2=i=0∑w(d)C(w(d),i)=2w(d)。
容易发现
f
(
n
)
f(n)
f(n) 是一个积性函数。
∑
i
=
1
m
f
(
n
i
)
=
f
(
n
)
∑
i
=
1
m
f
(
i
)
f
(
g
c
d
(
n
,
i
)
)
\displaystyle\sum_{i = 1}^mf(ni)=f(n)\sum_{i=1}^m\frac{f(i)}{f(gcd(n,i))}
i=1∑mf(ni)=f(n)i=1∑mf(gcd(n,i))f(i)。 接下来推导式子:
∑
i
=
1
m
f
(
i
)
f
(
g
c
d
(
n
,
i
)
)
=
∑
d
∣
n
1
f
(
d
)
∑
i
=
1
⌊
m
d
⌋
f
(
i
d
)
∗
[
g
c
d
(
n
d
,
i
)
=
1
]
\sum_{i=1}^m\frac{f(i)}{f(gcd(n,i))}=\sum_{d|n}\frac{1}{f(d)}\sum_{i=1}^{\lfloor\frac{m}{d}\rfloor}f(id)*[gcd(\frac{n}{d},i) = 1]
i=1∑mf(gcd(n,i))f(i)=d∣n∑f(d)1i=1∑⌊dm⌋f(id)∗[gcd(dn,i)=1]
∑
d
∣
n
1
f
(
d
)
∑
t
∣
n
d
μ
(
t
)
∑
i
=
1
⌊
m
t
∗
d
⌋
f
(
i
∗
t
∗
d
)
\sum_{d|n}\frac{1}{f(d)}\sum_{t|\frac{n}{d}}\mu(t)\sum_{i=1}^{\lfloor\frac{m}{t*d}\rfloor}f(i*t*d)
d∣n∑f(d)1t∣dn∑μ(t)i=1∑⌊t∗dm⌋f(i∗t∗d)
令
T
=
t
∗
d
T = t*d
T=t∗d
∑
T
∣
n
∑
d
∣
T
1
f
(
d
)
∗
μ
(
T
d
)
∑
i
=
1
⌊
m
T
⌋
f
(
i
∗
T
)
\sum_{T|n}\sum_{d|T}\frac{1}{f(d)}*\mu(\frac{T}{d})\sum_{i=1}^{\lfloor\frac{m}{T}\rfloor}f(i*T)
T∣n∑d∣T∑f(d)1∗μ(dT)i=1∑⌊Tm⌋f(i∗T)
令
g
(
T
)
=
∑
d
∣
T
1
f
(
d
)
∗
μ
(
T
d
)
g(T) = \displaystyle\sum_{d|T}\frac{1}{f(d)}*\mu(\frac{T}{d})
g(T)=d∣T∑f(d)1∗μ(dT),得到:
∑
T
∣
n
g
(
T
)
∑
i
=
1
⌊
m
T
⌋
f
(
i
∗
T
)
\sum_{T|n}g(T)\sum_{i=1}^{\lfloor\frac{m}{T}\rfloor}f(i*T)
T∣n∑g(T)i=1∑⌊Tm⌋f(i∗T)
观察
g
(
T
)
g(T)
g(T),
g
(
T
)
g(T)
g(T) 显然是一个积性函数,可以用欧拉筛预处理。
g
(
p
)
g(p)
g(p) 显然为
1
2
−
1
=
−
1
2
\frac{1}{2} - 1=-\frac{1}{2}
21−1=−21
g
(
p
k
)
g(p^k)
g(pk) 显然为
1
2
−
1
2
=
0
\frac{1}{2}-\frac{1}{2} = 0
21−21=0
由此可以观察到,
g
(
T
)
g(T)
g(T) 只有在
T
T
T 的最高幂次不大于 1 的情况下不为 0,对于
n
n
n 的因子 T,只需要枚举其质因子的组合即可,由于
n
≤
1
0
7
n \leq 10^7
n≤107,枚举质因子复杂度约为
8
∗
2
8
8*2^8
8∗28
考虑离线暴力计算 ∑ i = 1 ⌊ m T ⌋ f ( i ∗ T ) \displaystyle\sum_{i=1}^{\lfloor\frac{m}{T}\rfloor}f(i*T) i=1∑⌊Tm⌋f(i∗T),将每一组询问枚举质因子组合并将子询问维护到数列中,对子询问排序离线计算。 每种质因子组合 p 最多计算一次 m p \frac{m}{p} pm,复杂度和调和级数比较接近,约为 n log n n\log n nlogn
总复杂度为 O ( n log n + T ( log n + 8 ∗ 2 8 ) ) O(n \log n + T(\log n +8*2^8)) O(nlogn+T(logn+8∗28))
代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e7 + 10;
const int mod = 1e9 + 7;
typedef long long ll;
bool ispri[maxn];
int f[maxn], g[maxn], inv2 = (mod + 1) / 2, n ,m, pri[maxn], t, mindiv[maxn], ans[maxn];
vector<int> p;
struct node {
int n, T, m, id;
node() {}
node(int ni,int Ti,int mi,int idi) {
n = ni;
T = Ti;
m = mi;
id = idi;
}
bool operator < (const node &rhs) const{
if (T != rhs.T) return T < rhs.T;
return m < rhs.m;
}
};
vector<node> q;
void sieve(int n) {
ispri[0] = ispri[1] = true;
pri[0] = 0; f[1] = 1, g[1] = 1, mindiv[1] = 1;
for (int i = 2; i <= n; i++) {
if (!ispri[i]) {
pri[++pri[0]] = i;
f[i] = 2;
g[i] = mod - inv2;
mindiv[i] = i;
}
for (int j = 1; j <= pri[0] && i * pri[j] <= n; j++) {
ispri[i * pri[j]] = true;
if (i % pri[j] == 0) {
f[i * pri[j]] = f[i];
mindiv[i * pri[j]] = mindiv[i];
break;
} else {
mindiv[i * pri[j]] = pri[j];
f[i * pri[j]] = 2 * f[i];
g[i * pri[j]] = 1ll * g[i] * g[pri[j]] % mod;
}
}
}
}
int main() {
sieve(10000000);
scanf("%d",&t);
int id = 0;
while (id++, t--) {
scanf("%d%d",&n,&m);
p.clear();
int tmp = n;
while (tmp != 1) {
if (mindiv[tmp] != mindiv[tmp / mindiv[tmp]])
p.push_back(mindiv[tmp]);
tmp /= mindiv[tmp];
}
int v = p.size();
for (int i = 0; i < (1 << v); i++) {
int T = 1;
for (int j = 0; j < v; j++)
if ((i >> j) & 1) T *= p[j];
q.push_back(node(n,T,m / T * T,id));
}
}
sort(q.begin(),q.end());
int T = 0, w = 0, j = 0;
for (auto it : q) {
if (it.T != T) {
T = it.T, j = it.T, w = 0;
}
for (; j <= it.m; j += T)
w = (w + f[j]) % mod;
ans[it.id] = (ans[it.id] + 1ll * g[T] * w * f[it.n] % mod) % mod;
}
for (int i = 1; i < id; i++)
printf("%d\n",ans[i]);
return 0;
}