Cod sursa(job #264746)

Utilizator Omega91Nicodei Eduard Omega91 Data 22 februarie 2009 18:07:24
Problema Fractii Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.23 kb
#include <cstdio>
#include <cmath>

const int NMAX = 1000000;

char er[(NMAX >> 4) + 3] = {};

void compute_sieve()
{
	int i, j;
	const int a = (int)sqrt(NMAX) >> 1;
	const int b = NMAX >> 1;
	for (i = 1; i <= a; ++i)
		if (! (er[i >> 3] & (1 << (i & 7))) )
			for (j = (i * (i + 1)) << 1; j < b; j += (i << 1) + 1)
				er[j >> 3] |= 1 << (j & 7);
}

int epow(int a, int n)
{
	if (!n) return 1;
	if (n & 1) {
		int x = epow(a, (n - 1) >> 1);
		return a * x * x;
	}
	else {
		int x = epow(a, n >> 1);
		return x * x;
	}
}

inline bool iscomp(int x)
{return er[x >> 3] & (1 << (x & 7));}

inline int totient(int x)
{
	int k = 0, i, d, ans = 1;
	while (!(x & 1)) {
		x >>= 1;
		++k;
	}
	if (k) ans *= 1 << (k - 1);
	for (i = 1; iscomp(x >> 1); ++i) {
		d = (i << 1) + 1;
		if (!(x % d)) {
			k = 0;
			do  {
				x /= d;
				++k;
			} while ( !(x % d) );
			ans *= (d - 1) * pow(d, k - 1);
		}
	}
	if (x - 1) ans *= x - 1;
	return ans;
}



unsigned long long solve(int n)
{
	unsigned long long s = 1;
	int i;
	for (i = 2; i <= n; ++i)
		s += 2 * totient(i);
	return s;
}

int main()
{
	int N;
	compute_sieve();
	freopen("fractii.in", "r", stdin);
	freopen("fractii.out", "w", stdout);
	scanf("%d", &N);
	printf("%llu ", solve(N));
	printf("\n");
	return 0;	
}