http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1363
[egin{aligned}
&sum_{i=1}^nfrac{in}{(i,j)}\
=&nsum_{d|n}sum_{i=1}^{frac nd}left[left(i,frac nd
ight)=1
ight]i\
=&nleft(1+sum_{d|n,d
eq n}sum_{i=1}^{leftlfloorfrac {n}{2d}
ight
floor}left[left(i,frac nd
ight)=1
ight]
ight)\
=&n+frac n2sum_{d|n,d
eq 1}dvarphi(d)
end{aligned}
]
重点是统计(sumlimits_{d|n,d eq 1}dvarphi(d))
[egin{aligned}
&sum_{d|n,d
eq 1}dvarphi(d)\
=&prodsum_{j=0}^{c_i}p_i^j imesvarphileft(p_i^j
ight)-1\
=&prodleft(1+sum_{j=1}^{c_i}p_i^{2j-1}left(p_i-1
ight)
ight)-1\
=&prodleft(1+frac{p_i^{2c_i+1}-p_i}{p_i+1}
ight)-1
end{aligned}
]
质因子分解统计就可以了,时间复杂度(Oleft(Tsqrt n ight))。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 100000;
const int p = 1000000007;
bool notp[N + 3];
int T, n, prime[N + 3], num = 0, ni[N + 3];
void Euler_shai() {
for (int i = 2; i <= N; ++i) {
if (!notp[i]) prime[++num] = i;
for (int j = 1; j <= num && prime[j] * i <= N; ++j) {
notp[prime[j] * i] = true;
if (i % prime[j] == 0) break;
}
}
ni[1] = 1;
for (int i = 2; i <= N; ++i)
ni[i] = 1ll * (p - p / i) * ni[p % i] % p;
}
int ipow(int a, int b) {
int r = 1, w = a;
while (b) {
if (b & 1) r = 1ll * r * w % p;
w = 1ll * w * w % p;
b >>= 1;
}
return r;
}
int cal(int x) {
int ret = 1, ci;
for (int i = 1, pi = 2; i <= num && pi * pi <= x; pi = prime[++i]) {
if (x % pi == 0) {
ci = 1; x /= pi;
while (x % pi == 0) x /= pi, ++ci;
ret = 1ll * ret * (1ll * (ipow(pi, 2 * ci + 1) - pi + p) % p * ni[pi + 1] % p + 1) % p;
}
}
if (x > 1) {
ret = 1ll * ret * ((1ll * x * x % p * x % p - x + p) % p * ipow(x + 1, p - 2) % p + 1) % p;
}
return ret;
}
int main() {
Euler_shai();
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
printf("%lld
", (1ll * n * ni[2] % p * (cal(n) - 1) % p + n) % p);
}
return 0;
}