Cod sursa(job #3296655)

Utilizator rapidu36Victor Manz rapidu36 Data 15 mai 2025 10:47:58
Problema Frac Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.23 kb
#include <fstream>
#include <vector>
#include <bitset>

using namespace std;

const int RMAX = 110000;
const long long VMIN = 1;
const long long VMAX = 1LL << 61;

vector <int> prime;
vector <long long> dp;

void ciurul()
{
    ///construieste prime = vector cu numerele prime <= 10^6
    bitset <RMAX+1> c;
    for (int d = 2; d * d <= RMAX; d++)
    {
        if (!c[d])
        {
            for (int m = d * d; m <= RMAX; m += d)
            {
                c[m] = 1;
            }
        }
    }
    for (int i = 2; i <= RMAX; i++)
    {
        if (!c[i])
        {
            prime.push_back(i);
        }
    }
}

void desc(long long x)
{
    int i = 0, np = (int)prime.size();
    while (i < np && (long long)prime[i] * prime[i] <= x)
    {
        if (x % prime[i] == 0)
        {
            dp.push_back(prime[i]);
            while (x % prime[i] == 0)
            {
                x /= prime[i];
            }
        }
        i++;
    }
    if (x != 1)
    {
        dp.push_back(x);
    }
}

long long nr_prime_cu(long long n, long long x)
{
    int nd = (int)dp.size();
    long long nr = 0;
    ///generam multimile de indici
    ///(submultimi ale lui {0, 1,... nd-1})
    for (int multime = 0; multime < (1 << nd); multime++)
    {
        bool aduna = true;
        long long prod_dp = 1;
        for (int i = 0; i < nd; i++)
        {
            if (multime & (1 << i))///i apartine multime
            {
                aduna = (!aduna);
                prod_dp *= dp[i];
            }
        }
        if (aduna)
        {
            nr += n / prod_dp;
        }
        else
        {
            nr -= n / prod_dp;
        }
    }
    return nr;
}

int main()
{
    ifstream in("frac.in");
    ofstream out("frac.out");
    ciurul();
    long long n, p;
    in >> n >> p;
    desc(n);
    long long st = VMIN, dr = VMAX, rez = dr + 1;
    while (st <= dr)
    {
        long long m = (st + dr) / 2;
        if (nr_prime_cu(m, n) >= p)
        {
            rez = m;
            dr = m - 1;
        }
        else
        {
            st = m + 1;
        }
    }
    out << rez << "\n";
    in.close();
    out.close();
    return 0;
}