Cod sursa(job #50911)

Utilizator scapryConstantin Berzan scapry Data 9 aprilie 2007 13:13:49
Problema Fractii Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.34 kb
#include <assert.h>
#include <stdio.h>

enum { maxn = 1000001 };

int pop[maxn]; //is it a power of a prime (0 if not)
int fact[maxn]; //one factor of each number
int tot[maxn]; //"lafaiala"
bool bad[maxn];
int n;
long long ans;

void calc_primes()
{
	long long i, now = 3;

	for(now = 2; now <= n; now++) {
		if(bad[now]) continue;
		fact[now] = now;

		//mark all powers of this prime
		for(i = now; i <= n; i *= now) {
			assert(pop[i] == 0);
			pop[i] = now;
			//not marking bad yet
		}

		//mark all multiples of this prime
		for(i = now; i <= n; i += now) {
			bad[i] = true;
			fact[i] = now;
		}
	}
}

int calc_tot(int num)
{
	if(pop[num]) { //p^e
		assert(num % pop[num] == 0);

		return (pop[num] - 1) * (num / pop[num]);
	}
	else { //p^e * a
		assert(fact[num] != 0);
		assert(num % fact[num] == 0);

		int one = fact[num], two = num / fact[num];

		while(two % fact[num] == 0) {
			one *= fact[num];
			two /= fact[num];
		}

		return tot[one] * tot[two];
	}
}

void go()
{
	int numitor;

	tot[1] = 1;

	for(numitor = 2; numitor <= n; numitor++) {
		tot[numitor] = calc_tot(numitor);
		ans += tot[numitor];
	}

	ans *= 2;
	ans++;
}

int main()
{
	FILE *f = fopen("fractii.in", "r");
	if(!f) return 1;
	fscanf(f, "%d", &n);
	fclose(f);
	f = fopen("fractii.out", "w");
	if(!f) return 1;

	calc_primes();
	go();

	fprintf(f, "%lld\n", ans);
	fclose(f);
	return 0;
}