Cod sursa(job #109368)

Utilizator alextheroTandrau Alexandru alexthero Data 25 noiembrie 2007 10:30:35
Problema Pairs Scor 50
Compilator cpp Status done
Runda preONI 2008, Runda 1, Clasele 11-12 Marime 1.37 kb
#include <stdio.h>

#define nmax 100005
#define valMax 1000001
#define pmax 1005
#define max(i,j) ((i) > (j) ? (i) : (j))

int n, P, ct = 0, tot;
int p[pmax], a[nmax], vz[1005], vmax = 0;
char e[valMax];

int prim(int x)
{
	for(int i = 1; i <= P; i++)
	{
		if(x % p[i] == 0) return 0;
		if(p[i] * p[i] >= x) return 1;
	}
	return 1;
}

void test(int x, int sign)
{
	if(x == 1) return ;
	ct++;
	int t = 0;
	for(int i = 1; i * x <= vmax; i++)
		if(e[i  * x]) t++;
	t = t * (t - 1) / 2;
	tot = tot + (sign) * t;
	return ;
}

void back(int z, int y, int sign)
{
	if(z == P + 1) test(y, sign);
	else 
	{
		if((long long)y * p[z] <= vmax) back(z + 1, y * p[z], sign * -1);
		back(z + 1, y, sign);
	}
}

int gcd(int x, int y)
{
	if(y == 0) return x;
	else return gcd(y, x % y);
}

int main()
{
	freopen("pairs.in", "r", stdin);
	freopen("pairs.out", "w", stdout);

	scanf("%d", &n);
	for(int i = 1; i <= n; i++) 
	{
		scanf("%d", &a[i]);
		vmax = max(vmax, a[i]);
		e[a[i]] = 1;
	}

	for(int i = 2; i <= 1000; i++)
		if(prim(i)) p[++P] = i;

	tot = n * (n - 1) / 2;
	back(1, 1, 1);

	for(int j = 1001; j <= vmax; j += 2)
		if(prim(j))
		{
			vz[0] = 0;
			for(int x = 1; x * j <= vmax; x++)
				if(e[x * j]) vz[++vz[0]] = x;
			if(vz[0] > 0)
			{
				for(int i = 1; i <= vz[0]; i++)
					for(int j = i + 1; j <= vz[0]; j++)
						if(gcd(vz[i], vz[j]) == 1) tot--;
			}
		}


	printf("%d\n", tot);

	return 0;
}