码迷,mamicode.com
首页 > 其他好文 > 详细

UVA 11426 GCD - Extreme (II) (数论|欧拉函数)

时间:2015-08-18 22:43:05      阅读:231      评论:0      收藏:0      [点我收藏+]

标签:

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

思路:首先可以看出可以递推求出ans[n],因为ans[n-1]+f(n),其中f(n)表示小于n的数与n的gcd之和

问题转化为了求f(n),因为小于n的数与n的gcd一定是n的因数,

所以f(n)可以表示为sum(i)*i,其中sum(i)表示所有和n的gcd为i的数的数量,我们要求满足gcd(a, n) = i,的个数,可以转化为求gcd(a/i, n/i) = 1的个数,

于是可以发现sun(i) = phi(n/i),这里枚举n的因数的方法仿照素数筛法,时间复杂度为O(nlogn).

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii (pair<int, int>)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int maxn = 5000000;
//const int INF = 0x3f3f3f3f;
int n; 
LL ans[5000000];

int phi[maxn];
void phi_table(int n) {
	for(int i = 2; i <= n; i++) phi[i] = 0;
	phi[1] = 1;
	for(int i = 2; i <= n; i++) if(!phi[i])
		for(int j = i; j <= n; j+=i) {
			if(!phi[j]) phi[j] = j;
			phi[j] = phi[j] / i * (i-1);
		}
} 

void init() {
	phi_table(4000000);
	ans[1] = 0;
	for(int i = 1; i <= 4000000; i++) {
		for(int j = i*2; j <= 4000000; j+=i) {
			ans[j] += phi[j/i]*i; 
		}
	}
	for(int i = 2; i <= 4000000; i++) ans[i] += ans[i-1];
}

int main() {
    //freopen("input.txt", "r", stdin);
	init(); //cout << phi[3] << endl;
	while(scanf("%d", &n) == 1 && n) {
		cout << ans[n] << endl;
	}
    return 0;
}






版权声明:本文为博主原创文章,未经博主允许不得转载。

UVA 11426 GCD - Extreme (II) (数论|欧拉函数)

标签:

原文地址:http://blog.csdn.net/u014664226/article/details/47761045

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!