Cod sursa(job #15197)

Utilizator airineivAirinei Vasile airineiv Data 11 februarie 2007 02:29:11
Problema Fractii Scor 40
Compilator cpp Status done
Runda Arhiva de probleme Marime 10.07 kb
#include "stdio.h"
#include "math.h"

void ProcessDivisors(unsigned int r, unsigned int modulus, unsigned divizor[10], long long &k)
{
	unsigned int j, p, q, s, t, m, u;
	switch(r)
	{
	case 1:
		{
			if(modulus==1)
				k++;
			else if(modulus>1)
			{
				k += (modulus / divizor[0]) * (divizor[0]-1);
				k += modulus % divizor[0];
			}
			break;
		}
	case 2:
		{
			k += (modulus/divizor[0])*(divizor[0] -1);
			k += modulus % divizor[0];
			m = modulus/divizor[1];
			if(m == 1)
				k--;
			else if(m > 1)
			{
				k -= (m / divizor[0]) * (divizor[0]-1);
				k -= m % divizor[0];
			}
			break;
		}
	case 3:
		{
			p = q = 1;
			for(j=0; j<2; j++)
			{
				p *= divizor[j];
				q *= (divizor[j] -1);
			}
			k += (modulus/p)*q;
			t = modulus % p;
			if(t == 1)
				k++;
			else if(t > 1)
			{
				k += (t/divizor[0]) * (divizor[0]-1);
				k += t%divizor[0];
				m = t / divizor[1];
				if(m==1)
					k--;
				else if(m>1)
				{
					k -= (m / divizor[0]) * (divizor[0]-1);
					k -= m % divizor[0];
				}
			}

			m = modulus/divizor[2];
			if(m==1)
				k--;
			else if(m>1)
			{
				k -= (m / divizor[0]) * (divizor[0]-1);
				k -= m % divizor[0];
				m = m / divizor[1];
				if(m==1)
					k++;
				else if(m>1)
				{
					k += (m / divizor[0]) * (divizor[0]-1);
					k += m % divizor[0];
				}
			}

			break;
		}
	case 4:
		{
			p = q = 1;
			for(j=0; j<3; j++)
			{
				p *= divizor[j];
				q *= (divizor[j] -1);
			}
			k += (modulus/p)*q;
			t = modulus % p;
			if(t==1)
				k++;
			else if(t>1)
			{
				p =  p / divizor[2];
				q = q / (divizor[2]-1);
				k += (t/p) * q;
				s = t%p;
				if(s==1)
					k++;
				else if(s>1)
				{
					k += (s/divizor[0]) * (divizor[0] - 1);
					k += s % divizor[0];
				}
				m = s / divizor[1];
				if(m == 1)
					k--;
				else if(m>1)
				{
					k -= (m / divizor[0]) * (divizor[0]-1);
					k -= m % divizor[0];
				}
				m = t / divizor[2];
				if(m == 1)
					k--;
				else if(m>1)
				{
					k -= (m/p)*q;
					s = m%p;
					if(s == 1)
						k--;
					else if(s > 1)
					{
						k -= (s/divizor[0]) * (divizor[0] - 1);
						k -= s % divizor[0];
						m = s / divizor[1];
						if(m == 1)
							k++;
						else if(m>1)
						{
							k += (m / divizor[0]) * (divizor[0]-1);
							k += m % divizor[0];
						}
					}

				}
			}

			m = modulus/divizor[3];
			p = q = 1;
			for(j=0; j<3; j++)
			{
				p *= divizor[j];
				q *= (divizor[j] -1);
			}
			k -= (m/p)*q;
			t = m%p;
			if(t==1)
				k--;
			else if(t>1)
			{
				p =  p / divizor[2];
				q = q / (divizor[2]-1);
				k -= (t/p) * q;
				s = t%p;
				if(s==1)
					k--;
				else if(s>1)
				{
					k -= (s/divizor[0]) * (divizor[0] - 1);
					k -= s % divizor[0];
				}
				m = s / divizor[1];
				if(m == 1)
					k++;
				else if(m>1)
				{
					k += (m / divizor[0]) * (divizor[0]-1);
					k += m % divizor[0];
				}
				m = t / divizor[2];
				if(m == 1)
					k++;
				else if(m>1)
				{
					k += (m/p)*q;
					s = m%p;
					if(s == 1)
						k++;
					else if(s > 1)
					{
						k += (s/divizor[0]) * (divizor[0] - 1);
						k += s % divizor[0];
						m = s / divizor[1];
						if(m == 1)
							k--;
						else if(m>1)
						{
							k -= (m / divizor[0]) * (divizor[0]-1);
							k -= m % divizor[0];
						}
					}

				}
			}
			break;
		}
	case 5:
		{
			p = q = 1;
			for(j=0; j<4; j++)
			{
				p *= divizor[j];
				q *= (divizor[j] -1);
			}
			k += (modulus/p)*q;
			t = modulus % p;
			if(t==1)
				k++;
			else if(t>1)
			{
				p = p/divizor[3];
				q = q/(divizor[3]-1);
				k += (t/p)*q;
				m = t%p;
				if(m==1)
					k++;
				else if(m>1)
				{
					p = p/divizor[2];
					q = q/(divizor[2]-1);
					k += (m/p)*q;
					s = m%p;
					if(s==1)
						k++;
					else if(s>1)
					{
						k += (s/divizor[0])*(divizor[0]-1);
						k += s%divizor[0];
						u = s/divizor[1];
						if(u==1)
							k--;
						else if(u>1)
						{
							k -= (u/divizor[0])*(divizor[0]-1);
							k -= u%divizor[0];
						}
					}
					s = m/divizor[2];
					if(s==1)
						k--;
					else if(s>1)
					{
						k -= (s/divizor[0])*(divizor[0]-1);
						k -= s%divizor[0];
						u = s/divizor[1];
						if(u==1)
							k++;
						else if(u>1)
						{
							k += (u/divizor[0])*(divizor[0]-1);
							k += u%divizor[0];
						}
					}
				}
				m = t/divizor[3];
				if(m==1)
					k--;
				else if(m>1)
				{
					p = divizor[0] * divizor[1];
					q = (divizor[0]-1) * (divizor[1] -1);
					k -= (m/p)*q;
					s = m%p;
					if(s==1)
						k--;
					else if(s>1)
					{
						k -= (s/divizor[0])*(divizor[0]-1);
						k -= s%divizor[0];
						u = s/divizor[1];
						if(u==1)
							k++;
						else if(u>1)
						{
							k += (u/divizor[0])*(divizor[0]-1);
							k += u%divizor[0];
						}
					}
					s = m/divizor[2];
					if(s==1)
						k++;
					else if(s>1)
					{
						k += (s/divizor[0])*(divizor[0]-1);
						k += s%divizor[0];
						u = s/divizor[1];
						if(u==1)
							k--;
						else if(u>1)
						{
							k -= (u/divizor[0])*(divizor[0]-1);
							k -= u%divizor[0];
						}
					}
				}
			}

			t = modulus/divizor[4];
			if(t==1)
				k--;
			else if(t>1)
			{
				p = q = 1;
				for(j=0; j<3; j++)
				{
					p *= divizor[j];
					q *= (divizor[j] -1);
				}
				k -= (t/p)*q;
				m = t%p;
				if(m==1)
					k--;
				else if(m>1)
				{
					p = p/divizor[2];
					q = q/(divizor[2]-1);
					k -= (m/p)*q;
					s = m%p;
					if(s==1)
						k--;
					else if(s>1)
					{
						k -= (s/divizor[0])*(divizor[0]-1);
						k -= s%divizor[0];
						u = s/divizor[1];
						if(u==1)
							k++;
						else if(u>1)
						{
							k += (u/divizor[0])*(divizor[0]-1);
							k += u%divizor[0];
						}
					}
					s = m/divizor[2];
					if(s==1)
						k++;
					else if(s>1)
					{
						k += (s/divizor[0])*(divizor[0]-1);
						k += s%divizor[0];
						u = s/divizor[1];
						if(u==1)
							k--;
						else if(u>1)
						{
							k -= (u/divizor[0])*(divizor[0]-1);
							k -= u%divizor[0];
						}
					}
				}
				m = t/divizor[3];
				if(m==1)
					k++;
				else if(m>1)
				{
					p = divizor[0] * divizor[1];
					q = (divizor[0]-1) * (divizor[1] -1);
					k += (m/p)*q;
					s = m%p;
					if(s==1)
						k++;
					else if(s>1)
					{
						k += (s/divizor[0])*(divizor[0]-1);
						k += s%divizor[0];
						u = s/divizor[1];
						if(u==1)
							k--;
						else if(u>1)
						{
							k -= (u/divizor[0])*(divizor[0]-1);
							k -= u%divizor[0];
						}
					}
					s = m/divizor[2];
					if(s==1)
						k--;
					else if(s>1)
					{
						k -= (s/divizor[0])*(divizor[0]-1);
						k -= s%divizor[0];
						u = s/divizor[1];
						if(u==1)
							k++;
						else if(u>1)
						{
							k += (u/divizor[0])*(divizor[0]-1);
							k += u%divizor[0];
						}
					}
				}
			}
			break;
		}
	case 6:
		{
			p = q = 1;
			for(j=0; j<5; j++)
			{
				p *= divizor[j];
				q *= (divizor[j] -1);
			}
			k += (modulus/p)*q;
			t = modulus % p;
			if(t==1)
				k++;
			else if(t>1)
			{
				long long i=0;
				ProcessDivisors(5, t, divizor, i);
				k+=i;
			}
			m = modulus/divizor[5];
			long long i=0;
			ProcessDivisors(5, m, divizor, i);
			k -= i;
			break;
		}

	case 7:
		{
			p = q = 1;
			for(j=0; j<6; j++)
			{
				p *= divizor[j];
				q *= (divizor[j] -1);
			}
			k += (modulus/p)*q;
			t = modulus % p;
			if(t==1)
				k++;
			else if(t>1)
			{
				long long i=0;
				ProcessDivisors(6, t, divizor, i);
				k+=i;
			}
			m = modulus/divizor[6];
			long long i=0;
			ProcessDivisors(6, m, divizor, i);
			k -= i;
			break;
		}
	default:
		{
			p = q = 1;
			for(j=0; j<r-1; j++)
			{
				p *= divizor[j];
				q *= (divizor[j] -1);
			}
			k += (modulus/p)*q;
			t = modulus % p;

			for(j=1; j<=t; j++)
			{
				bool relativePrime = true;
				for(s=0; s<r-1; s++)
				{
					if(j % divizor[s] == 0)
					{
						relativePrime = false;
						break;
					}
				}
				if(relativePrime)
					k++;
			}
			m = modulus/divizor[r-1];
			for(j=1; j<=m; j++)
			{
				bool relativePrime = true;
				for(s=0; s<r-1; s++)
				{
					if(j % divizor[s] == 0)
					{
						relativePrime = false;
						break;
					}
				}
				if(relativePrime)
					k--;
			}
			break;
		}
	}
}

int main(void)
{
	FILE *fin, *fout;
	if((fin = fopen("fractii.in", "r"))==NULL)
		return 0;
	if((fout = fopen("fractii.out", "w"))==NULL)
		return 0;
	unsigned int N, i, j, r, mod, prod1, prod2;
	bool Eratostene[1000001];
	unsigned long long n, fi, p;
	unsigned int divizor[10];
	fscanf(fin, "%d", &N);
	int *t = new int[N+1]; 
	for(i=0; i<=N; i++)
	{
		Eratostene[i] = true;
		t[i] = 0;
	}	
	t[1] = 1;
	for(i=2; i*i<=N; i++)
	{
		if(Eratostene[i])
		{
			for(j=2; i*j<=N; j++)
				Eratostene[i*j] = false;
		}
	}
	for(i=2; i<=N; i++)
	{
		if(Eratostene[i])
		{
			t[i] = i-1;
			p = i;
			while(p<=N)
			{
				t[p] = (i-1)*(p/i);
				p *= i;
			}
		}
	}
	for(i=2; i<=N; i++)
	{
		if(t[i] == 0)
		{
			for(j=2; j<=i; j++)
			{
				if(Eratostene[j])
				{
					p = i;
					r = 0;
					while(p%j==0)
					{
						p = p/j;
						r++;
					}
					if(r>0 && t[p] != 0 && p%j!=0)
					{
						t[i] = t[p]*(j-1);
						for(int k=1; k<=r-1; k++)
							t[i] *= j;
						break;
					}
				}
			}
		}
	}
	n=N;
	for(i=2; i<=N; i++)
	{
		r=0;
		fi = t[i];
		if(!Eratostene[i])
		{
			p=i;	
			for(j=2; j<=i; j++)
			{
				if(Eratostene[j] && p%j == 0)
				{
					while(p%j==0)
						p = p/j;
					divizor[r++] = j;
					if(p==1)
						break;
				}
			}
		}
		mod = N%i;
		if(mod == 0)
			fi *= N/i;
		else
		{
			fi *= N/i;
			if(Eratostene[i])
				fi += mod;
			else
			{
				if(mod==1)
					fi++;
				else
				{
					long long k=0;
					ProcessDivisors(r, mod, divizor, k);
					fi += k;
				}
			}
		}
		n+=fi;
	}
	
	fprintf(fout, "%llu", n);
	fclose(fin);
	fclose(fout);
	delete []t;
	t = NULL;
	return 0;
}