链接
B − 牛 半 仙 的 妹 子 g c d B-牛半仙的妹子gcd B−牛半仙的妹子gcd
题目描述
牛半仙想知道 ∑ 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。
输出
一行一个整数,表示任意三个妹子的相同度之和。
样例输入
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}的最大公约数。
思路
朴素想法
n
3
n^3
n3
再考虑一下,我们可以先
n
2
n^2
n2求出
g
c
d
(
i
,
j
)
gcd(i,j)
gcd(i,j),然后再和k去求
g
c
d
gcd
gcd就好了
代码
#include<iostream>
#include<cstdio>
using namespace std;
int n, ans;
int a[100005];//a[i]表示最大公约数为i的数对(i,j)个数
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[gcd(i, j)]++;
for (int i = 1; i <= n; ++i) //枚举原i,j的最大公约数
for (int j = 1; j <= n; ++j)
ans += a[i] * gcd(i, j);//原本有a[i]个,那贡献就是现在产生的gcd*原有个数
printf("%d", ans);
return 0;
}