题意

[51 Nod 1584] 加权约数和_ii
其中
[51 Nod 1584] 加权约数和_ii_02
[51 Nod 1584] 加权约数和_ii_03
[51 Nod 1584] 加权约数和_ii_04表示[51 Nod 1584] 加权约数和_ii_05的约数和

题目分析

[51 Nod 1584] 加权约数和_ii_06,则[51 Nod 1584] 加权约数和_ii_07

且有
[51 Nod 1584] 加权约数和_ii_08
[51 Nod 1584] 加权约数和_ii_09
[51 Nod 1584] 加权约数和_ii_10

发现[51 Nod 1584] 加权约数和_ii_11可以递推:
[51 Nod 1584] 加权约数和_ii_12
那么就可以[51 Nod 1584] 加权约数和_ii_13预处理了。

然后每次[51 Nod 1584] 加权约数和_ii_14回答就完了。

CODE

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1000005;
const int mod = 1000000007;
int Cnt, Prime[N], mu[N];
LL ans[N], sd[N], a[N], d[N], f[N];
bool IsnotPrime[N];

void init() {
d[1] = 1, a[1] = 1, mu[1] = 1;
for(int i = 2; i < N; ++i) {
if(!IsnotPrime[i])
Prime[++Cnt] = i, d[i] = a[i] = 1+i, mu[i] = -1;
for(int j = 1, k; j <= Cnt && i * Prime[j] < N; ++j) {
IsnotPrime[k = i * Prime[j]] = 1;
if(i % Prime[j] == 0) {
mu[k] = 0;
a[k] = a[i] * Prime[j] + 1;
d[k] = d[i] / a[i] * a[k];
break;
}
mu[k] = -mu[i];
a[k] = 1 + Prime[j];
d[k] = d[i] * a[k];
}
}
for(int i = 1; i < N; ++i) {
sd[i] = (sd[i-1] + (d[i]%=mod)) % mod;
f[i] = i*d[i]%mod*(2*sd[i]-d[i]+mod)%mod;
}
for(int i = 1; i < N; ++i) if(mu[i])
for(int j = i; j < N; j += i)
ans[j] = (ans[j] + 1ll*mu[i]*i*i%mod*f[j/i]%mod + mod) % mod;
for(int i = 1; i < N; ++i) ans[i] = (ans[i-1] + ans[i]) % mod;
}
int main () {
init();
int T, ks = 0, N; scanf("%d", &T);
while(T--) scanf("%d", &N), printf("Case #%d: %lld\n", ++ks, ans[N]);
}