Cod sursa(job #1330501)

Utilizator cbanu96Banu Cristian cbanu96 Data 30 ianuarie 2015 18:42:11
Problema Frac Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.04 kb
#include <bits/stdc++.h>

using namespace std;

#define CIURMAX 110000
#define ll long long

bool isPrime[CIURMAX];
vector<int> primes;
ll N;

ll gcd(ll A, ll B)
{
    ll r;
    while (B != 0) {
        r = A % B;
        A = B;
        B = r;
    }

    return A;
}

void ciur()
{
    memset(isPrime, true, sizeof(isPrime));

    primes.push_back(2);

    for (int i = 3; i < CIURMAX; i+= 2) {
        if (!isPrime[i])
            continue;
        primes.push_back(i);
        for (int j = i + i; j < CIURMAX; j += i)
            isPrime[j] = 0;
    }
}

ll solve(ll A)
{
    ll B = N;
    vector<int> p;

    for (int i = 0; i < primes.size() && primes[i] * primes[i] < B; i++) {
        if (!(B % primes[i]))
            p.push_back(primes[i]);

        while (!(B % primes[i]))
            B /= primes[i];
    }

    if (B > 1)
        p.push_back(B);

    int n = p.size();

    ll sol = 0;
    for (int conf = 1; conf < (1 << n); conf++ ) {
        ll prod = 1;
        int k = 0;
        for (int i = 0; i < n; i++)
            if (conf & (1 << i))
                prod *= p[i], k++;

        if (k % 2)
            sol += A / prod;
        else
            sol -= A / prod;
    }

    return A - sol;
}

int main() {
    ifstream f("frac.in");
    ofstream g("frac.out");

    ciur();

    ll P;

    f >> N >> P;

    if (N == 1) {
        g << P;
        return 0;
    }

    ll l, r;
    l = 0;
    r = (1LL<<62);

    ll ans = 0;

    while (l < r) {
        ll mid = (l+r)/2;
        cerr << l << " " << r << ": ";

        ll sol = solve(mid);
        cerr << mid << " - " << sol << endl;
        if (sol < P)
            l = mid+1;
        else if (sol > P)
            r = mid-1;
        else {
            if (gcd(mid, N) == 1) {
                ans = mid;
                l = r + 1;
            } else {
                r = mid;
            }
        }
    }

    if (ans == 0 && l == r && gcd(l, N) == 1)
        ans = l;

    g << ans << endl;
}