题目:求sum(gcd(i,j)),(1<=i<j<=n)

题解:我们设答案为ans[n],ans[n]=ans[n-1]+gcd(1,n)+gcd(2,n)+...+gcd(n-1,n);接下来的问题是如何求gcd(1,n)+gcd(2,n)+...+gcd(n-1,n);

设g[n]=gcd(1,n)+gcd(2,n)+...+gcd(n-1,n); 设p(i)表示目前为止与n的gcd为i的数有几个?则g[n]=sum(p[i])(1<=i<=n);

假设gcd(x,n)=i,那么显然gcd(x/i,n/i)=1,所以p[i]即为phi(n/i)的值。

所以我们只需预处理出phi的值就可以了。

程序:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#define maxn 4000009
using namespace std;
typedef long long ll;
ll phi[maxn],g[maxn],f[maxn];
int n;
int main()
{
  scanf("%d",&n);
  for (int i=1;i<maxn;i++) phi[i]=0;
  phi[1]=1;
  for (int i=2;i<maxn;i++)
  {
      if (phi[i]) continue;
      for (int j=i;j<maxn;j+=i)
      {
        if (!phi[j]) phi[j]=j;
      phi[j]-=phi[j]/i;    
    }
  }
  for (int i=1;i<maxn;i++)
  for (int j=i+i;j<maxn;j+=i)
  g[j]+=phi[j/i]*i;
  f[2]=g[2];
  for (int i=3;i<maxn;i++) f[i]=f[i-1]+g[i];
  while (n)
  {
      printf("%lld\n",f[n]);
      scanf("%d",&n);
  }
  return 0;
}

 

posted on 2018-01-05 21:17  nhc2014  阅读(302)  评论(0编辑  收藏  举报