题意:给定多个n,求所有的gcd(i,j)之和{1<=i<j<=n}。
分析:因为每一次的gcd必然是j的因子,我们只要对每个j的因子计算贡献即可,比如当前的因子为x,x|j,那么对答案的贡献为phi(j/x)*x,phi()是欧拉函数。O(nlogn)
代码:
#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=4000010;
const int MAX=151;
const int mod=100000000;
const int MOD1=100000007;
const int MOD2=100000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000009;
const ll INF=10000000010;
typedef double db;
typedef unsigned long long ull;
int f[N],a[N],q[N];
ll ans[N],sum[N];
void deal(int n) {
int i,j,k=0,w;
for (i=1;i<=n;i++) f[i]=i;
memset(q,0,sizeof(q));
for (i=2;i<=n;i++) {
if (!q[i]) { a[++k]=i; }
for (j=1;j<=k;j++) {
if (a[j]*i>n) break ;
q[a[j]*i]=1;
if (i%a[j]==0) break ;
}
}
for (i=1;i<=k;i++)
for (j=a[i];j<=n;j+=a[i]) f[j]=f[j]/a[i]*(a[i]-1);
memset(ans,0,sizeof(ans));
for (i=1;i<=n;i++)
for (j=2*i;j<=n;j+=i) ans[j]+=f[j/i]*i;
sum[0]=0;
for (i=1;i<=n;i++) sum[i]=sum[i-1]+ans[i];
}
int main()
{
int n;
deal(4000000);
while (scanf("%d", &n)&&n) printf("%lld\n", sum[n]);
return 0;
}