Cod sursa(job #2095600)

Utilizator arcoC. Nicolae arco Data 27 decembrie 2017 19:18:15
Problema Fractii Scor 0
Compilator c Status done
Runda Arhiva de probleme Marime 2.45 kb
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <stdint.h>

typedef unsigned int uint;

uint *ciur(uint n, uint *size);
bool binsearch(uint *vector, uint size, uint key);
uint64_t phi(uint *cr, uint size, uint n);

int main(void)
{
	FILE *in = fopen("fractii.in", "r");
	FILE *out = fopen("fractii.out", "w");
	if(in != NULL && out != NULL)
	{
		uint size, n, i = 1;
		fscanf(in, "%u%*c", &n);
		uint *cr = ciur(n, &size);

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

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

	return 0;
}

uint64_t phi(uint *cr, uint size, uint n)
{
	if(binsearch(cr, size, n))
	{
		return n - 1;
	}
	else
	{
		uint i = 0;
		double calc = n;
		for(; i < size && n > 1; i++)
		{
			uint p = 0;
			while(n % cr[i] == 0)
			{
				p++;
				n /= cr[i];
			}
			if(p)
			{
				calc *= (1.0 - (1.0 / cr[i]));
			}
		}
		return (uint64_t)calc;
	}
}

bool binsearch(uint *vector, uint size, uint key)
{
	uint p = 0, q = size;
	while(p <= q)
	{
		uint mid = (p + q) / 2;
		if(vector[mid] == key)
		{
			return true;
		}
		else if(vector[mid] > key)
		{
			p = mid + 1;
		}
		else if(vector[mid] < key)
		{
			q = mid - 1;
		}
	}

	return false;
}

uint *ciur(uint n, uint *size)
{
	uint psize = 10, pgrow = 5, pidx = 0;
	uint *primes = malloc(sizeof(uint) * psize);
	uint *vector = calloc(n + 2, sizeof(uint));
	if(vector != NULL && primes != NULL)
	{
		uint i = 1;
		for(; i <= n; i++)
		{
			vector[i] = i;
		}

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

		uint last = 2;
		while(1)
		{
			bool found = false;
			i = last + 1;
			for(; i <= n; i++)
			{
				if(vector[i])
				{
					if((pidx + 1) >= psize)
					{
						psize += pgrow;
						primes = realloc(primes, sizeof(uint) * psize);
						if(primes == NULL)
						{
							printf("Failed to realloc\n");
							exit(EXIT_FAILURE);
						}
					}

					primes[pidx++] = i;
					last = i;
					found = true;
					vector[i] = 0;
					break;
				}
			}

			if(found)
			{
				uint mark = last;
				for(; mark <= n; mark += last)
				{
					vector[mark] = 0;
				}
			}
			else
			{
				break;
			}
		}

		*size = pidx;
		free(vector);
		return primes;
	}
	else
	{
		printf("Failed to init memory\n");
	}
}