Cod sursa(job #73186)

Utilizator scapryConstantin Berzan scapry Data 17 iulie 2007 12:01:28
Problema Indep Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.98 kb
#include <cassert>
#include <cstring>
#include <iostream>
#include <fstream>
using namespace std;

enum { maxn = 501, maxval = 1001 };

class bignum
{
	enum { maxdigs = 1024 };

	int digs;
	int d[maxdigs];

	void zero();

	void validate() const;

public:
	bignum();
	void operator=(int);
	void operator+=(const bignum &);
	void operator-=(const bignum &);
	void operator*=(int);

	friend ostream& operator<<(ostream &, const bignum &);

};

void bignum::zero()
{
	memset(d, 0, sizeof(d));
	digs = 1;
}

inline
void bignum::validate() const
{
	int i;

	assert(digs > 0 && digs < maxdigs);

	//first
	if(digs != 1)
		assert(d[digs - 1] != 0);

	//filled
	for(i = 0; i < digs; i++)
		assert(d[i] >= 0 && d[i] <= 9);

	//empty
	for(i = digs; i < maxdigs; i++)
		assert(d[i] == 0);
}

bignum::bignum()
{
	zero();
}

void bignum::operator=(int val)
{
	validate();

	assert(val >= 0 && val <= 9 && "one digit please");

	zero();
	d[0] = val;

	validate();
}

void bignum::operator+=(const bignum &o)
{
	validate();

	int i, t = 0, stop = max(digs, o.digs);
	for(i = 0; i < stop || t; i++)
	{
		d[i] += o.d[i] + t;
		t = d[i] / 10;
		d[i] %= 10;
	}

	digs = i;

	validate();
}

void bignum::operator-=(const bignum &o)
{
	validate();

	int i;
	for(i = 0; i < digs; i++)
	{
		d[i] -= o.d[i];

		if(d[i] < 0)
		{
			d[i] += 10;
			assert(d[i] >= 0);
			d[i + 1]--;
		}
	}

	while(digs > 1 && d[digs - 1] == 0)
		digs--;

	validate();
}

void bignum::operator*=(int o)
{
	assert(o == 2 && "can only multiply by 2");

	validate();

	int i, t = 0;
	for(i = 0; i < digs || t; i++)
	{
		d[i] = d[i] * 2 + t;
		t = d[i] / 10;
		d[i] %= 10;
	}

	digs = i;

	validate();
}

ostream &operator<<(ostream &s, const bignum &n)
{
	for(int i = n.digs - 1; i >= 0; i--)
		s << n.d[i];

	n.validate();

	return s;
}

int n;
int val[maxn];
bignum ans;
bignum two[maxval]; //2^i - 1

/**
 * returns true if num was successfully decomposed into a product of prime numbers.
 */
bool decompose(int num, int &factors, int *factor)
{
	int now;

	factors = 0;

	for(now = 2; num != 1; now++)
	{
		if(num % now == 0)
		{
			factor[factors++] = now;
			num /= now;

			if(num % now == 0)
				return false;
		}
	}

	return true;
}

void go()
{
	int i, j;
	int factors, factor[maxval];
	int count;

	bignum one;
	one = 1;

	two[0] = 1;
	for(i = 1; i < maxval; i++)
	{
		two[i] = two[i - 1];
		two[i] *= 2;
	}
	for(i = 0; i < maxval; i++)
		two[i] -= one;

	for(i = 1; i < maxval; i++)
	{
		if(decompose(i, factors, factor)) //product of unique prime factors
		{
			//count values divisible by i
			count = 0;
			for(j = 0; j < n; j++)
				if(val[j] % i == 0)
					count++;

			if(count == 0)
				continue;

			if(factors % 2) //odd, subtract
			{
				ans -= two[count];
			}
			else //even, add
			{
				ans += two[count];
			}
		}
	}
}

int main()
{
	int i;
	fstream f("indep.in", ios_base::in);
	if(!f) return 1;

	f >> n;
	for(i = 0; i < n; i++)
		f >> val[i];

	f.close();
	f.open("indep.out", ios_base::out);
	if(!f) return 1;

	go();

	f << ans << endl;
	f.close();
	return 0;
}