​传送门​

如果求出 51nod1584 加权约数和 (莫比乌斯反演)_i++
那么 51nod1584 加权约数和 (莫比乌斯反演)_质因子_02 就是答案

有一个结论是
51nod1584 加权约数和 (莫比乌斯反演)_预处理_03
证明(口胡):考虑某一个质因子 51nod1584 加权约数和 (莫比乌斯反演)_预处理_04,假设最后在约数中为 51nod1584 加权约数和 (莫比乌斯反演)_i++_05
令如果 51nod1584 加权约数和 (莫比乌斯反演)_预处理_0451nod1584 加权约数和 (莫比乌斯反演)_预处理_07 中为 51nod1584 加权约数和 (莫比乌斯反演)_预处理_08,如果 51nod1584 加权约数和 (莫比乌斯反演)_i++_09 那么我们在 51nod1584 加权约数和 (莫比乌斯反演)_预处理_07 中填上 51nod1584 加权约数和 (莫比乌斯反演)_预处理_11,否则在 51nod1584 加权约数和 (莫比乌斯反演)_i++_12 中填上 51nod1584 加权约数和 (莫比乌斯反演)_预处理_13
显然 51nod1584 加权约数和 (莫比乌斯反演)_预处理_04 只会在一边出现而且所有的因数考虑完了
如果是 51nod1584 加权约数和 (莫比乌斯反演)_i++_15 的话考虑一下上面的过程想一想最后是什么数,有:
51nod1584 加权约数和 (莫比乌斯反演)_i++_16
51nod1584 加权约数和 (莫比乌斯反演)_预处理_17
51nod1584 加权约数和 (莫比乌斯反演)_i++_18
51nod1584 加权约数和 (莫比乌斯反演)_质因子_19
51nod1584 加权约数和 (莫比乌斯反演)_质因子_20
已经可以 51nod1584 加权约数和 (莫比乌斯反演)_i++_21 预处理,51nod1584 加权约数和 (莫比乌斯反演)_预处理_22 查询了,但 51nod1584 加权约数和 (莫比乌斯反演)_预处理_23 较大
考虑一个 51nod1584 加权约数和 (莫比乌斯反演)_i++_24 的贡献,对所有 51nod1584 加权约数和 (莫比乌斯反演)_i++_25 都有贡献,于是就可以 51nod1584 加权约数和 (莫比乌斯反演)_i++_26 预处理,51nod1584 加权约数和 (莫比乌斯反演)_i++_27 查询
51nod1584 加权约数和 (莫比乌斯反演)_i++_28 同理
顺带一提,51nod1584 加权约数和 (莫比乌斯反演)_i++_29 可以用线性筛,考虑质数次幂的贡献即可
51nod1584 加权约数和 (莫比乌斯反演)_预处理_30
51nod1584 加权约数和 (莫比乌斯反演)_预处理_31

#include<bits/stdc++.h>
#define cs const
using namespace std;
cs int Mod = 1e9 + 7, N = 1e6 + 5;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
void Add(int &a, int b){ a = add(a, b); }
int T, n, mu[N], sig[N], Ssig[N];
bool isp[N]; int prim[N], tot;
int Mn[N], vlMn[N], ans[N], f[N], g[N];
void prework(){
n = 1e6;
mu[1] = sig[1] = 1;
for(int i = 2; i <= n; i++){
if(!isp[i]){
prim[++tot] = i;
sig[i] = i+1; mu[i] = Mod-1;
Mn[i] = 1; vlMn[i] = i+1;
}
for(int j = 1; j <= tot; j++){
if(prim[j] * i > n) break;
int k = prim[j] * i; isp[k] = true;
if(i % prim[j] == 0){
Mn[k] = Mn[i]; mu[k] = 0;
vlMn[k] = add(mul(vlMn[i], prim[j]), 1);
sig[k] = mul(vlMn[k], sig[Mn[k]]);
break;
}
Mn[k] = i; vlMn[k] = prim[j]+1;
mu[k] = mul(mu[i], mu[prim[j]]);
sig[k] = mul(sig[i], sig[prim[j]]);
}
}
for(int i = 1; i <= n; i++){
f[i] = mul(mu[i], mul(i,i));
Ssig[i] = add(Ssig[i-1], sig[i]);
g[i] = mul(mul(i, sig[i]), dec(mul(2,Ssig[i]),sig[i]));
}
for(int i = 1; i <= n; i++)
for(int j = 1, up=n/i; j <= up; j++)
Add(ans[i*j], mul(f[i],g[j]));
for(int i = 1; i <= n; i++) Add(ans[i], ans[i-1]);
}
int main(){
prework();
cin >> T; for(int i = 1; i <= T; i++){
scanf("%d", &n); cout << "Case #" << i << ": " << ans[n] << '\n';
} return 0;
}