Cod sursa(job #2092502)

Utilizator arcoC. Nicolae arco Data 21 decembrie 2017 20:26:10
Problema Fractii Scor 20
Compilator c Status done
Runda Arhiva de probleme Marime 2.44 kb
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <math.h>

uint64_t euler(uint64_t n);
bool is_prime(uint64_t n);
uint64_t phi(uint64_t n);
uint64_t *cr(uint64_t n, uint64_t *dx);

uint64_t dx;
uint64_t *c;

int main(void)
{
	FILE *in = fopen("fractii.in", "r");
	FILE *out = fopen("fractii.out", "w");
	if(in != NULL && out != NULL)
	{
		uint64_t n;
		uint64_t s = 0;
		fscanf(in, "%llu", &n);
		
		c = cr(n, &dx);

		uint64_t i = 1;
		for(; i <= n; i++)
		{
			s += euler(i);
		}
		fprintf(out, "%llu\n", (2 * s) - 1);

		free(c);
		fclose(in);
		fclose(out);
	}
	else
	{
		printf("Error\n");
	}

	return 0;
}

uint64_t *cr(uint64_t n, uint64_t *dx)
{
	uint64_t psize = 10;
	uint64_t pgrow = 5;
	uint64_t pidx = 0;
	uint64_t *primes = malloc(sizeof(uint64_t) * psize);
	uint64_t *vector = malloc(sizeof(uint64_t) * (n + 3));

	if(vector != NULL && primes != NULL)
	{
		uint64_t i = 0;
		for(; i <= n; i++)
		{
			vector[i] = i;
		}
		vector[1] = 0;
		primes[pidx++] = 2;

		i = 2;
		for(; i <= n; i += 2)
		{
			vector[i] = 0;
		}

		uint64_t last = 2;
		while(1)
		{
			bool found = false;

			uint64_t j = last + 1;
			for(; j <= n; j++)
			{
				if(vector[j])
				{
					if((pidx + 1) >= psize)
					{
						psize += pgrow;
						primes = realloc(primes, sizeof(uint64_t) * psize);
						if(primes == NULL)
						{
							printf("Failed to realloc\n");
							exit(EXIT_FAILURE);
						}
					}
					primes[pidx++] = vector[j];
					found = true;
					last = j;
					break;
				}
			}
			if(found)
			{
				uint64_t mark = vector[j];
				uint64_t inc = vector[j];
				for(; mark <= n; mark += inc)
				{
					vector[mark] = 0;
				}
			}
			else
			{
				break;
			}
		}

		*dx = pidx;
		free(vector);

		return primes;
	}
	else
	{
		printf("FAILED TO INIT\n");
	}
}

bool is_prime(uint64_t n)
{
	if((n == 1) || (n % 2 == 0 && n != 2))
	{
		return false;
	}
	else
	{
		uint64_t i = 2;
		for(; i * i <= n; i++)
		{
			if(n % i == 0)
			{
				return false;
			}
		}

		return true;
	}
}

uint64_t euler(uint64_t n)
{
	if(is_prime(n))
	{
		return n - 1;
	}
	else
	{
		return phi(n);
	}
}

uint64_t phi(uint64_t n)
{
	double calc = n;
	uint64_t i = 0;
	for(; i < dx; i++)
	{
		if(n % c[i] == 0)
		{
			calc *= (1.0 - (double)(1.0 / c[i]));
		}
	}

	return (uint64_t)calc;
}