Pagini recente » Cod sursa (job #2551883) | Cod sursa (job #2550779) | Cod sursa (job #3297238)
#include <bits/stdc++.h>
#define NMAX 1000001
#define NRD 7
using namespace std;
int nr_div[NMAX]; ///numarul de divizori primi ai fiecarui numar in care acestia apar la puterea 1
int prod_div[NMAX]; ///produsul divizorilor primi ai fiecarui numar
int divizori_primi[NMAX][NRD]; ///lista divizorilor primi ai fiecarui numar in care acestia apar la puterea 1
void eratostene() ///calculam ciurul lui eratostene
{
bitset<NMAX/2> ciur;
vector<int> prime; ///numerele prime pana la 1000000
for(int i=3; i*i<NMAX; i+=2)
{
if(ciur[i/2]==0)
{
for(int j=i*i; j<NMAX; j+=2*i)
ciur[j/2]=1;
}
}
prime.push_back(2);
for(int i=3; i<NMAX; i+=2)
{
if(ciur[i/2]==0)
prime.push_back(i);
}
for(int i=1; i<NMAX; i++)
prod_div[i]=1;
for(auto p : prime) ///calculam listele de divizori primi ale fiecarui numar
{
for(int d=p; d<NMAX; d+=p)
{
if(d%(p*p)!=0) ///daca divizorul apare o singura data
{
divizori_primi[d][nr_div[d]]=p;
nr_div[d]++;
}
prod_div[d]*=p;
}
}
}
int nr_prime_cu[NMAX]; ///numarul de numere prime cu fiecare numar
int main()
{
ifstream cin("mins.in");
ofstream cout("mins.out");
eratostene();
int c, d;
cin >> c >> d;
///vom gasi numarul de perechi de numere (x, y), pentru care x<c si y<d, care sunt prime intre ele
long long nr_drepte=0;
for(int x=1; x<c; x++)
{
int produs=prod_div[x]; ///produsul divizorilor primi ai lui x
if(x==produs) ///daca x este egal cu produs (adica daca fiecare divizor prim apare la puterea 1)
{
///vom calcula numarul de numere prime cu x mai mici ca d folosind principiul includerii si excluderii
int nr_d=nr_div[x]; ///numarul de divizori primi ai lui x
for(int m=0; m<(1<<nr_d); m++)
{
bool adun=1; ///adunam sau scadem
int p=1; ///produsul numerelor ai caror biti din reprezentarea in baza 2 ai lui m sunt 1
for(int bit=0; bit<nr_d; bit++)
{
if((m&(1<<bit))!=0) ///daca bitul este setat
{
adun=(!adun);
p*=divizori_primi[x][bit];
}
}
if(adun)
nr_prime_cu[x]+=(d-1)/p;
else
nr_prime_cu[x]-=(d-1)/p;
}
nr_drepte+=nr_prime_cu[x];
}
else ///altfel, numarul de numere prime cu x mai mici ca d va fi egal cu numarul de numere mai mici ca d prime cu produs (care a fost deja calculat fiindca produs<x)
{
nr_drepte+=nr_prime_cu[produs];
nr_prime_cu[x]=nr_prime_cu[produs];
}
}
cout << nr_drepte; ///afisam numarul de drepte
return 0;
}