Cod sursa(job #2951269)

Utilizator TudosieRazvanTudosie Marius-Razvan TudosieRazvan Data 5 decembrie 2022 20:09:12
Problema Pairs Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 1.85 kb
#include <fstream>
#include <climits>
#include <vector>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <bitset>
#include <map>
#include <cstring>
#include <algorithm>
#define NMAX 1000003


using namespace std;



ifstream fin("pairs.in");
ofstream fout("pairs.out");

long long n;
int maxim = INT_MIN;
int nrDivPrimi[NMAX];//numarul de divizori primi ai numarului o
bool ePatratPerject[NMAX],frecv[NMAX];//daca e patrat perfect numarul i si daca exista in vectorul initial de numere

void facProcesari()
{
	//aici fac ciurul si incerc sa imi procesez elementele
	nrDivPrimi[1] = 1;//1 nu e prim duh
	for (int i = 2; i <= maxim; i++)
	{
		if (nrDivPrimi[i] == 0)
		{
			//tac pac e prim
			//parcurg toti multiplii lui i
			for (int j = i; j <= maxim; j += i) {
				nrDivPrimi[j]++;
				if (j % (i * i) == 0)
				{
					//practic e multiplu de patrat perfect->e si el patrat perfect
					ePatratPerject[j] = 1;
				}
			}
			
		}
	}
}

int main()
{
	fin >> n;
	for (int i = 1; i <= n; i++)
	{
		int x;
		fin >> x;
		maxim = max(maxim, x);//iau numarul maxim 
		frecv[x] = true;//pun ca am numarul asta
	}

	facProcesari();
	long long int num = 0;//acuma vine pinex
	for (int i = 2; i <= maxim; i++)
	{
		if (!ePatratPerject[i])
		{
			//nu e multiplu de patrat perfect
			long long cnt = 0;//merg cum am mers si la ciur si vad care sunt multiplii lui care apar printre numere
			for (int k = i; k <= maxim; k+=i)
			{
				if (frecv[k] == true)
				{
					cnt++;
				}
			}
			//acuma vine smecheria, daca am un numar par de divizori primi, inseamna ca am reuniunea a n intervale unde n par->se scad
			if (nrDivPrimi[i] % 2 == 0)
			{
				num -= cnt * (cnt - 1) / 2;
			}
			else {
				num += cnt * (cnt - 1) / 2;
			}
		}
	}
	fout << 1LL * n * (n - 1) / 2 - num;
	return 0;
}