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
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;
}