Pagini recente » Cod sursa (job #1665422) | Borderou de evaluare (job #2772090) | Cod sursa (job #1860231) | Cod sursa (job #1140707) | Cod sursa (job #2534186)
#include <fstream>
#include <bitset>
using namespace std;
const int VMAX = 1000001;
int N, xMax;
bitset<VMAX> M;
///Vector caracteristic al multimii de numere distincte M
///M[i] = 1 <==> i apartine multimii M
unsigned char nrdiv[VMAX];
///nrdiv[i] = cate numere prime distincte apar in descompunerea
/// in factori a lui i
bitset<VMAX> ciurp;
///Vector caracteristic al numerelor pentru care descompunerea
///in factori nu are factori primi distincti, adica:
///
///ciurp[i] = 1 <==> i are un divizor prim la o putere >= 2
/// (i se divide cu patratul unui numar prim)
/*
Ideea este sa ca am numarul TOTAL de imperecheri - care este n * (n-1) / 2, adica toate cu toate,
dar nu toate aceste combinatii sunt permise
Astfel, noi vom elimina din numarul total combinatiile nepermise
Luam un numar prim, vedem cati multiplii are in sirul nostru, calculam numarul de combinatii intre ei
care este nr * (nr - 1) / 2 si scadem numarul acesta din numarul total de combinatii
ATENTIE
Daca exista un numar compus, care mai multi divizori primi in sir, acesta va fi scazut de mai multe ori decat
este necesar.
De aceea, ca sa putem scadea un numar cu multiplii lui, trebuie sa aiba numar IMPAR de divizori
*/
ifstream cin( "pairs.in" );
ofstream cout( "pairs.out" );
void citire()
{
int x;
cin >> N;
for ( int i = 1; i <= N; i++ )
cin >> x, M[x] = 1,
xMax = max(xMax, x);
}
int main()
{
citire();
long long sol = 1LL * N * ( N - 1 ) / 2;
for ( int i = 2; i <= xMax; i++ )
{
if ( nrdiv[i] == 0 )
{
///Crestem numarul factorilor primi pentru numerele
///divizibile cu i
for ( int j = i; j <= xMax; j += i )
nrdiv[j]++;
}
//
if ( ciurp[i] == 0 )
{
///Marcam toti multiplii de i * i
long long ii = 1LL * i * i;
for ( long long jj = ii; jj <= xMax; jj += ii )
ciurp[jj] = 1;
//
///Determinam cate dintre numerele i, 2*i, 3*i,...,[xMax/i]*i
///apartin multimii M
long long rez = 0;
for ( int j = i; j <= xMax; j += i )
if ( M[j] == 1 )
rez++;
//
rez = rez * ( rez - 1 ) / 2; // calculam numarul de combinatii facute de un numar cu toti multiplii lui
( !(nrdiv[i] & 1) ) ? // verificam numarul de divizori ca sa vedem daca il adunam sau il scadem
sol += rez : sol -= rez;
}
}
cout << sol;
return 0;
}