牛半仙的妹子gcd \operatorname{牛半仙的妹子gcd} 牛半仙的妹子gcd
题目链接: nowcoder 212919 \operatorname{nowcoder\ 212919} nowcoder 212919
关于这场比赛
到牛客看:
题目
牛半仙有
n
n
n 个妹子,每个妹子有一个属性值,第
i
i
i 个妹子的属性值为
n
−
i
+
1
n - i + 1
n−i+1。
牛半仙认为
k
k
k 个妹子
{
b
1
,
b
2
…
b
k
}
\{b_1,b_2…b_k\}
{b1,b2…bk} 的相同度为
g
c
d
(
a
b
1
,
a
b
2
…
a
b
k
)
gcd(a_{b_1},a_{b_2}…a_{b_k})
gcd(ab1,ab2…abk)。
牛半仙想知道
∑
i
=
1
n
∑
j
=
1
n
∑
k
=
1
n
g
c
d
(
i
,
j
,
k
)
\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n gcd(i,j,k)
∑i=1n∑j=1n∑k=1ngcd(i,j,k) 的值。
输入
一行一个整数 n n n。
输出
一行一个整数,表示任意三个妹子的相同度之和。
样例输入
2
样例输出
9
数据范围
对于
40
%
40\%
40% 的数据,
n
≤
200
n\le200
n≤200
对于
100
%
100\%
100% 的数据,
n
≤
1000
n\le1000
n≤1000
g
c
d
(
a
1
,
a
2
…
a
k
)
gcd(a_1,a_2…a_k)
gcd(a1,a2…ak) 表示
{
a
1
,
a
2
…
a
k
}
\{a_1,a_2…a_k\}
{a1,a2…ak} 的最大公约数。
思路
这道题有很多种做法,我选择了最简单的预处理(因为只会这个
还有莫比乌斯反演和欧拉两种做法。
预处理的主要思想就是先预处理出 gcd 中一边是 i i i,另一边从 1 1 1 枚举到 n n n 的 j j j,我们就是预处理数所有 g c d ( i , j ) gcd(i,j) gcd(i,j) 的和。
那与处理完之后,我们就可以枚举题目的 i i i 跟 j j j,因为前面预处理了,就可以省去枚举 k k k 的部分。
时间复杂度是 O ( n 2 l o g n ) O(n^2logn) O(n2logn),勉强能过。
比赛时
想了一会就想到了预处理的方法。
在看了一下复杂度应该可行就打完跑了。
代码
#include<cstdio>
using namespace std;
int n, a[1001], ans;
int gcd(int x, int y) {
if (!y) return x;
return gcd(y, x % y);
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
a[i] += gcd(i, j);//预处理出一对
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
ans += a[gcd(i, j)];//统计
printf("%d", ans);
return 0;
}