Cod sursa(job #841141)

Utilizator stoicatheoFlirk Navok stoicatheo Data 23 decembrie 2012 20:26:26
Problema Puteri Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.26 kb
using namespace std;

#include <vector>
#include <bitset>

#define II inline
#define ll long long
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define CC(v) memset((v),0,sizeof((v)))
#define mp make_pair

#define IN  "puteri.in"
#define OUT "puteri.out"
#define N_MAX 1<<17
#define MOD 65535

int a,b,c,mod,N,P[1<<8];
int nrdiv,K;
char A[N_MAX],B[N_MAX],C[N_MAX];
vector<bool> viz(1<<8),bo(1<<8);
char buffer[1<<20];

II void read(char &aux)
{
	aux = 0;
	for(;buffer[K] < '0' || buffer[K] > '9';++K);
	for(;buffer[K] >= '0' && buffer[K] <= '9';++K)
		aux = aux * 10 + buffer[K] - '0';
}

II void ciur()
{
	for(int i=4;i<=(1<<7);i+=2)
		viz[i] = true;
	P[++P[0]] = 2;
	
	for(int i=3;i<=(1<<7);i+=2)
	{
		if(viz[i])
			continue;
		P[++P[0]] = i;
		for(int j=i+i;j<=(1<<7);j+=i)
			viz[j] = true;
	}	
}

II void scan()
{
	freopen(IN,"r",stdin);
	freopen(OUT,"w",stdout);
	
	scanf("%d\n",&N);
	fread(buffer,1,1<<20,stdin);
	fclose(stdin);
	
	int V[N_MAX];
	char x,y,z;
	FOR(i,1,N)
	{
		read(x),read(y),read(z);
		V[i] = x * 10000 + y * 100 + z;
	}
	sort(V+1,V+N+1);
	FOR(i,1,N)
	{
		C[i] = V[i] % 100; 
		V[i] /= 100;
		B[i] = V[i] % 100;
		V[i] /= 100;
		A[i] = V[i];
	}	
}

II void make(int i)
{
	a = A[i] % mod;
	b = B[i] % mod;
	c = C[i] % mod;
}

II bool make_2(int i)
{
	a = A[i] % mod;
	b = B[i] % mod;
	c = C[i] % mod;
	if(a) a = mod - a;
	if(b) b = mod - b;
	if(c)  c = mod - c;
	if(a > 64 || b > 64 || c > 64)
		return false;
	return true;
}

II bool divide(int x)
{
	int aux = x;
	for(int i=2;i*i<=x;++i)
	{
		if(aux % i)
			continue;
		++nrdiv;
		aux /= i;
		if(!(aux % i) || !bo[i])
			return false;	
	}	
	if(aux>1)
		++nrdiv;
	return true;
}

II void solve()
{
	unsigned int C[66][66][66];
	ll rez(0);	
	
	for(mod=2;mod<=128;++mod)
	{
		nrdiv = 0;
		if(!viz[mod])
			nrdiv = 1;
		if(viz[mod] && !divide(mod) )
			continue;
		for(int i=N-1;i>=1;--i)
		{
			make(i+1);
			if(A[i] || B[i] || C[i])
				++C[a][b][c];
			
			if( make_2(i) )
			{
				int aux = C[a][b][c];
				if(aux) bo[mod] = true;
				rez += ((nrdiv&1)?aux:-aux);
			}
		}
		CC(C);
	}
	
	printf("%lld\n",rez);
}

int main()
{
	ciur();
	scan();
	solve();
//	printf("%d\n",clock() );

	return 0;
}