题目描述
for i=1 to n
for j=1 to n
sum+=gcd(i,j)
给出n求sum. gcd(x,y)表示x,y的最大公约数.
输入输出格式
输入格式:
n
输出格式:
sum
输入输出样例
输入样例#1:
2
输出样例#1:
5
说明
数据范围 30% n<=3000 60% 7000<=n<=7100 100% n<=100000
分析:求sum我们不可能把所有gcd全部求出来,但是有很多一样的gcd,因此我们可以统计每个gcd的个数,如gcd=k的倍数的个数为(n/k)*(n/k),这样我们把k的倍数减掉就好了,因此我们要倒着枚举k.
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; long long n,sum,d[100010]; int main() { scanf("%lld", &n); for (int k = n; k; k--) { d[k] = (n / k) * (n / k); for (int i = k + k; i <= n; i += k) d[k] -= d[i]; sum += d[k] * k; } printf("%lld ", sum); return 0; }