洛谷2398 GCD SUM

来源:互联网 发布:象过河软件怎么用 编辑:程序博客网 时间:2024/06/05 08:34

洛谷2398 GCD SUM
本题地址:
http://www.luogu.org/problem/show?pid=2398

题目描述

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

30%可直接暴力,70%可打表,就不说了,关键在于100%:
f[d]表示gcd=d(i,j)有多少对。那么sum(f[d]×d)就是答案,直接求f[d]有困难,我们可以用g[d]表示gcdd的倍数的(i,j)有多少对,则f[d]=g[d]f[2×d]f[3×d]f[4×d]f[5×d]...g[d]=(n/d)×(n/d)。可以按n,n1,n2...1的顺序来求f[d]。所以总时间应该是n/1+n/2+n/3+n/4+...n/n。这个东西欧拉当年研究过的,有兴趣的可以百度一下,只要记住它是nlogn级别的就好(想一想筛法)。

#include<cstdio>using namespace std;long long n,ans=0;long long f[110000],g[110000];int main(){    scanf("%d",&n);    for (int d=n;d>=1;--d)    {        f[d]=1ll*(1ll*n/d)*1ll*(n/d);            for (int i=d+d;i<=n;i+=d) f[d]-=f[i];        ans+=f[d]*d;    }    printf("%lld\n",ans);    return 0;}
0 0