UVA 11426 GCD - Extreme (II)

题目大意:
\(\sum_{i=1}^{N}\sum_{j=i+1}^{N}gcd(i,j)\)

解题报告:
我们设答案为\(s[n]\)
那么\(s[n]\)表示为\(s[n]=\sum_{i=1}^{n}f[n]\)
其中\(f[i]=\sum_{j=1}^{j=n}gcd(i,j)\),我们可以拆开\(f[i]\):
\(f[i]=\sum_{j=1}^{i}j*g[i,j]\)
\(g[n,i]\)为满足\(gcd(n,j)==i\)的j的个数,那么可以看出\(gcd(n,j)==j\)等价于\(gcd(n/i,j/i)=1\),所以实质上就是\(\phi(n/i)\)
综上我们可以先求出\(\phi\),推出\(f[i]\)之后再求出\(s[i]\)即可,其中推\(f[i]\)我们可以像线性筛一样的去推出,这样复杂度就是O(n)的了

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const int N=4000005;
int phi[N],prime[N],num=0;bool vis[N];
void solve(){
	int to;
	phi[1]=1;
	for(int i=2;i<N;i++){
		if(!vis[i]){
			prime[++num]=i;
			phi[i]=i-1;
		}
		for(int j=1;j<=num && i*prime[j]<N;j++){
			to=i*prime[j];vis[to]=true;
			if(i%prime[j])phi[to]=phi[i]*(prime[j]-1);
			else{
				phi[to]=phi[i]*prime[j];
				break;
			}
		}
	}
}
ll f[N],ans[N];
void work()
{
	solve();
	for(int i=1;i<N;i++)
		for(int j=i+i;j<N;j+=i)
			f[j]+=i*phi[j/i];
	for(int i=1;i<N;i++)
		ans[i]=ans[i-1]+f[i];
	int n;
	while(~scanf("%d",&n) && n)
		printf("%lld\n",ans[n]);
}

int main()
{
	work();
	return 0;
}

posted @ 2017-09-12 19:48  PIPIBoss  阅读(111)  评论(0编辑  收藏  举报