写题解前,先感谢meopass学长的指点,一语惊醒梦中人!!!
被这题卡得无心准备四六级了
题意:
\qquad T T T 组数据, 1 ≤ T ≤ 5 e 4 1\le T \le 5e4 1≤T≤5e4 , 求 ∑ i = 1 n i × n ( i , n ) , 1 ≤ n ≤ 1 e 9 \sum_{i=1}^n\frac{i\times n}{(i,n)},1 \le n \le 1e9 ∑i=1n(i,n)i×n,1≤n≤1e9 。
思路:
\qquad
a
n
s
=
∑
i
=
1
n
i
×
n
(
i
,
n
)
=
n
∑
i
=
1
n
i
(
i
,
n
)
=
n
×
(
1
+
∑
d
∣
n
d
×
ϕ
(
d
)
)
2
ans = \sum_{i=1}^n\frac{i\times n}{(i,n)}=n\sum_{i=1}^n\frac{i}{(i,n)}=\frac{n\times(1+\sum_{d|n}d\times \phi(d))}{2}
ans=∑i=1n(i,n)i×n=n∑i=1n(i,n)i=2n×(1+∑d∣nd×ϕ(d))
\qquad
令
F
[
n
]
=
∑
d
∣
n
d
×
ϕ
(
d
)
F[n]=\sum_{d|n}d \times \phi(d)
F[n]=∑d∣nd×ϕ(d) ,那么
a
n
s
=
n
×
(
F
[
n
]
+
1
)
2
ans = \frac{n \times (F[n] + 1)}{2}
ans=2n×(F[n]+1) 。
\qquad
由于
1
≤
n
≤
1
e
9
1 \le n \le 1e9
1≤n≤1e9 ,所以不能
O
(
n
)
O(n)
O(n) 预处理出所有的
ϕ
(
d
)
\phi(d)
ϕ(d) ,而且不能在
O
(
n
)
O(\sqrt{n})
O(n) 筛
d
d
d 的同时,算
ϕ
(
d
)
\phi(d)
ϕ(d) ,这样的复杂度我认为是
O
(
T
n
)
O(Tn)
O(Tn)的 。但是
d
×
ϕ
(
d
)
d \times \phi(d)
d×ϕ(d)是个积性函数,可以根据
n
n
n 的质因子去求
ϕ
(
d
)
\phi(d)
ϕ(d),先质因数分解,再BFS求
ϕ
(
d
)
\phi(d)
ϕ(d)(DFS可能会T) 。这样的复杂度大概是
O
(
T
n
)
O(T\sqrt{n})
O(Tn) 。
#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define linf 0x3f3f3f3f3f3f3f3f
#define ms(x,a) memset(x,a,sizeof(x))
#define debug cout<<endl<<"***"<<endl
using namespace std;
const int maxn = 1e6 + 10;
bool v[maxn];
int p[maxn],cnt;
ll phi[maxn];
void sieve() {
ms(v,0);
cnt = 0;
phi[1] = v[1] = 1;
for(int i = 2; i < maxn; ++i) {
if(!v[i])p[++cnt] = i,phi[i] = i - 1;
for(int j = 1; j <= cnt && i * p[j] < maxn; ++j) {
v[i * p[j]] = 1;
if(i % p[j] == 0) {
phi[i * p[j]] = phi[i] * p[j];
break;
}
phi[i * p[j]] = phi[i] * (p[j] - 1);
}
}
return ;
}
struct Node {
ll d,phi_d;
int pos;
};
ll fac[35],expo[35];
int tot;
inline void print(__int128 x) {
if(x < 0) {
putchar('-');
x =- x;
}
if(x > 9) print(x / 10);
putchar(x % 10 + '0');
}
__int128 calc(ll x) {
tot = 0;
for(int i = 1; i <= cnt && p[i] * p[i] <= x; ++i) {
if(x % p[i] == 0) {
fac[++tot] = p[i];
expo[tot] = 0;
while(x % p[i] == 0) {
x /= p[i];
expo[tot]++;
}
}
}
if(x > 1) {
fac[++tot] = x,expo[tot] = 1;
}
queue<Node>q;
__int128 res = 1;
for(int i = 1; i <= tot; ++i) {
ll xx = fac[i],yy = fac[i] - 1;
q.push({xx,yy,i + 1});
res += xx * yy;
for(int j = 2; j <= expo[i]; ++j) {
xx = xx * fac[i];
yy = yy * fac[i];
q.push({xx,yy,i + 1});
res += xx * yy;
}
}
int pos = 0;
while(q.size()) {
Node tmp = q.front();
q.pop();
ll x = tmp.d,y = tmp.phi_d;
int pos = tmp.pos;
if(pos <= tot) {
q.push({x,y,pos + 1});
ll A = fac[pos];
ll xx2 = x * A;
ll yy2 = y * (A - 1);
q.push({xx2,yy2,pos + 1});
res += xx2 * yy2;
for(int i = 2; i <= expo[pos]; ++i) {
xx2 = xx2 * A;
yy2 = yy2 * A;
q.push({xx2,yy2,pos + 1});
res += xx2 * yy2;
}
}
}
return res;
}
__int128 get_res(ll n) {
__int128 res = (calc(n) + 1) * n / 2;
return res;
}
int main() {
sieve();
int t;
scanf("%d",&t);
for(int ca = 1; ca <= t; ++ca) {
ll n;
scanf("%lld",&n);
__int128 ans = get_res(n);
print(ans);
puts("");
}
return 0;
}