Cod sursa(job #3297144)

Utilizator Lex._.Lexi Guiman Lex._. Data 21 mai 2025 16:15:20
Problema Mins Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.01 kb
#include <bits/stdc++.h>
#define NMAX 1000001
using namespace std;

bitset<NMAX/2> ciur;
vector<int> prime; ///numerele prime pana la 1000000
array<vector<int>, NMAX> divizori_primi; ///lista divizorilor primi ai fiecarui numar

void eratostene() ///calculam ciurul lui eratostene
{
    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(auto p : prime) ///calculam listele de divizori primi ale fiecarui numar
    {
        for(int d=p; d<NMAX; d+=p)
            divizori_primi[d].push_back(p);
    }
}

int main()
{
    ifstream cin("mins.in");
    ofstream cout("mins.out");
    eratostene();
    int c, d;
    cin >> c >> d;
    /*for(auto x : divizori_primi)
    {
        for(auto d : x)
            cout << d << " ";
        cout << "\n";
    }*/
    ///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;
    nr_drepte+=1; ///dreapta pentru care x=y

    array<int, NMAX> nr_prime_cu; ///numarul de numere prime cu fiecare numar
    for(int i=0; i<NMAX; i++) nr_prime_cu[i]=0;

    for(int x=2; x<c; x++)
    {
        int produs=1; ///produsul divizorilor primi ai lui x
        for(auto d : divizori_primi[x])
            produs*=d;
        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=divizori_primi[x].size(); ///numarul de divizori primi ai lui x
            for(int m=1; 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))==1) ///daca bitul este setat
                    {
                        adun=(!adun);
                        p*=divizori_primi[x][bit];
                    }
                }
                if(adun)
                    nr_prime_cu[x]+=d/p;
                else
                    nr_prime_cu[x]-=d/p;
                //cout << d/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 << "\n" << x << "  " << nr_prime_cu[x] << "\n\n";
    }
    /*for(auto x : nr_prime_cu) cout << x << " "; cout << "\n";*/
    cout << nr_drepte; ///afisam numarul de drepte

    return 0;
}