洛谷P2398 GCD SUM

题目描述

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\n", sum);

    return 0;
}

 

posted @ 2017-09-09 16:52  zbtrs  阅读(133)  评论(0编辑  收藏  举报