Cod sursa(job #1404412)

Utilizator mircea.dobreanuMircea Dobreanu mircea.dobreanu Data 28 martie 2015 09:23:59
Problema Pairs Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2 kb
#include <algorithm>
#include <bitset>
#include <fstream>
#include <vector>
using namespace std;

ifstream fin("pairs.in");
ofstream fout("pairs.out");
const int kMax = 1e5 + 5;
const int kSqrt = 1e3 + 5;
const int kVal = 1e6 + 5;
int n;
long long v[kMax];
bitset<kVal> isPrime, isUsed;
vector<int> primeList, divisors;

void sieve()
{
	isPrime.set();
	isPrime[0] = isPrime[1] = false;

	primeList.push_back(2);
	/*for (int j = 4; j < kVal; j += 2)
		isPrime[j] = false;*/

	for (int i = 3; i < kVal; i += 2)
	{
		if (isPrime[i])
		{
			primeList.push_back(i);
			if (i < kSqrt)
				for (int j = i * i; j < kVal; j += i)
					isPrime[j] = false;
		}
	}
}

void breakIntoDivisors()
{
	for (int i = 1; i <= n; ++i)
	{
		int cpy = v[i];
		for (size_t j = 0; j < primeList.size() && cpy != 1; ++j)
		{
			if (isPrime[cpy])
			{
				isUsed[cpy] = true;
				break;
			}
			while (!(cpy % primeList[j]))
			{
				isUsed[primeList[j]] = true;
				cpy /= primeList[j];
			}
		}
	}
}

void createDivisorsList()
{
	if (isUsed[2])
		divisors.push_back(2);

	for (int i = 3; i < kVal; i += 2)
		if (isUsed[i])
			divisors.push_back(i);
}

int cardDivBy(int divisor)
{
	int res = 0;
	for (int i = 1; i <= n; ++i)
		if (v[i] % divisor == 0)
			++res;
	return res;
}

long long noPairs(int card)
{
	return 1LL * card * (card - 1) / 2;
}

int main()
{
    sieve();
	fin >> n;
	for (int i = 1; i <= n; ++i)
		fin >> v[i];

	breakIntoDivisors();
	createDivisorsList();

	//Inclusion-exclusion principle
	int bits = divisors.size(), sz = (1 << divisors.size());
	long long res = 0;

	for (int bitMask = 0; bitMask < sz; ++bitMask)
	{
		int noBits = 0;
		long long factor = 1;
		for (int i = 0; i < bits; ++i)
		{
			if (bitMask & (1 << i))
			{
				++noBits;
				factor *= 1LL * divisors[i];
			}
		}
		if (noBits % 2)
            res -= noPairs(cardDivBy(factor));
		else
			res += noPairs(cardDivBy(factor));
	}
	fout << res << '\n';
	return 0;
}