题意:
定义 F(n)=∑i=1n∑j=1n[gcd(i,j)+lcm(i,j)⩾n] F ( n ) = ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) + l c m ( i , j ) ⩾ n ] ,其中 [] [ ] 是艾弗森约定,现在要求出 ansn=∑i=1nF(i) a n s n = ∑ i = 1 n F ( i ) .
思路:
如果定义
T(n)=∑i=1n∑j=1n[gcd(i,j)+lcm(i,j)=n]
T
(
n
)
=
∑
i
=
1
n
∑
j
=
1
n
[
g
c
d
(
i
,
j
)
+
l
c
m
(
i
,
j
)
=
n
]
,那么
Fn=i∗i−∑i=1n−1T(i)
F
n
=
i
∗
i
−
∑
i
=
1
n
−
1
T
(
i
)
,因为不可能存在
i⩾n
i
⩾
n
或者
j⩾n
j
⩾
n
时有
gcd(i,j)+lcm(i,j)=n
g
c
d
(
i
,
j
)
+
l
c
m
(
i
,
j
)
=
n
,看
T(n)
T
(
n
)
怎么算:
T(n)=∑d=1n∑i=1⌊nd⌋∑j=1⌊nd⌋[gcd(i,j)=1][i∗j∗d+d=n]
T
(
n
)
=
∑
d
=
1
n
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
n
d
⌋
[
g
c
d
(
i
,
j
)
=
1
]
[
i
∗
j
∗
d
+
d
=
n
]
=∑d=1n∑i=1⌊nd⌋∑j=1⌊nd⌋[gcd(i,j)=1][(i∗j+1)d=n]
=
∑
d
=
1
n
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
n
d
⌋
[
g
c
d
(
i
,
j
)
=
1
]
[
(
i
∗
j
+
1
)
d
=
n
]
=∑d|n∑i=1nd∑j=1nd[gcd(i,j)=1][(i∗j+1)d=n]
=
∑
d
|
n
∑
i
=
1
n
d
∑
j
=
1
n
d
[
g
c
d
(
i
,
j
)
=
1
]
[
(
i
∗
j
+
1
)
d
=
n
]
=∑d|n∑i=1nd∑j=1nd[gcd(i,j)=1][i∗j=nd−1]
=
∑
d
|
n
∑
i
=
1
n
d
∑
j
=
1
n
d
[
g
c
d
(
i
,
j
)
=
1
]
[
i
∗
j
=
n
d
−
1
]
=∑d|n∑i=1nd∑j=1nd[gcd(i,j)=1][j=nd−1i]
=
∑
d
|
n
∑
i
=
1
n
d
∑
j
=
1
n
d
[
g
c
d
(
i
,
j
)
=
1
]
[
j
=
n
d
−
1
i
]
=∑d|n∑i=1nd[gcd(i,nd−1i)=1]
=
∑
d
|
n
∑
i
=
1
n
d
[
g
c
d
(
i
,
n
d
−
1
i
)
=
1
]
=∑d|n∑i=1nd−1[gcd(i,nd−1i)=1]
=
∑
d
|
n
∑
i
=
1
n
d
−
1
[
g
c
d
(
i
,
n
d
−
1
i
)
=
1
]
记
f(x)=∑i|x[gcd(i,xi)=1]
f
(
x
)
=
∑
i
|
x
[
g
c
d
(
i
,
x
i
)
=
1
]
,如果
i
i
和互素,那么可以知道
i
i
要么完全拥有的素因子,要么完全没有
x
x
的素因子,暴力搜索一下素因子产生的因子即可,不用
gcd
g
c
d
去判断,因为那样时间就变成
O(nlg2n).....
O
(
n
lg
2
n
)
.
.
.
.
.
,会超时的。
#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 1e6 + 5;
const ll mod = 258280327;
using namespace std;
typedef pair<int, int> pa;
int a[maxn];
pa pri[1000]; int num;
void div(int x) {
while(x > 1) {
int now = a[x];
if(!num || pri[num - 1].first != now) pri[num++] = pa(now, 1);
else pri[num - 1].second++;
x /= now;
}
}
int vec[1000], cnt, T;
void dfs(ll &ans, int sol, int sum, int id, int flag) {
if(id == num) {
int y = sol / sum;
vec[cnt++] = sum;
if(!flag) ans++;
return ;
}
int k = 1, g = flag;
for(int i = 0; i <= pri[id].second; i++) {
if(!i || i == pri[id].second) flag = 0;
else flag = 1;
dfs(ans, sol, sum * k, id + 1, g | flag);
k *= pri[id].first;
}
}
ll ans[maxn], rec[maxn];
ll seq[maxn], f[maxn], tot[maxn];
void solve() {
int max_p = 0;
for(ll i = 1; i <= 1000000; i++) {
num = 0; div(i); cnt = 0;
dfs(f[i], i, 1, 0, 0);
rec[i] = i * i;
rec[i] = rec[i] - tot[i - 1];
for(int j = 0; j < cnt; j++) {
int x = vec[j];
seq[i] += f[x - 1];
}
tot[i] = tot[i - 1] + seq[i];
ans[i] = ans[i - 1] + rec[i];
}
}
int main() {
for(ll i = 2; i < maxn; i++) {
if(a[i]) continue;
a[i] = (int) i;
for(ll j = i * i; j < maxn; j += i) if(!a[j]) a[j] = i;
}
solve(); int n;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
printf("%lld\n", ans[n] % mod);
}
return 0;
}