Cod sursa(job #123235)

Utilizator peanutzAndrei Homorodean peanutz Data 15 ianuarie 2008 00:13:42
Problema Frac Scor 60
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.84 kb
#include <stdio.h>
#include <vector>

using namespace std;

#define pb push_back
#define sz size()

long long n, p;

inline short bit(int x, int i) { return ((x & (1<<i)) > 0); }

inline int cmmdc(int a, int b)
{
    while(a != b)
    {
        if(a > b)
            a -= b;
        else
            b -= a;
    }
    return a;
}

short nrbit[32000];

int main()
{
    freopen("frac.in", "r", stdin);
    freopen("frac.out", "w", stdout);
    
    scanf("%lld %lld\n", &n, &p);
    
    if(n == 1)
    {
        printf("%lld\n", p);
        return 0;
    }
    if(p == 1)
    {
        printf("1\n");
        return 0;
    }
    
    long long st = 1, last, dr = (1LL << 61), m, crt, aux = n;
    vector<int> v;
    int i, j;
    
    for(i = 2; (i << 1) < aux; ++i)
        if(!(aux%i))
        {
            v.pb(i);
            while(!(aux%i)) aux /= i;
        }
    if(aux > 1) v.pb(aux);
    int until = v.sz;
    for(i = 1; i < (1<<until); ++i) nrbit[i] = nrbit[i >> 1] + (i&1);
    vector<int> par, impar;

    for(i = 1; i < (1<<until); ++i)
    {
        for(j = 0, crt = 1; j < until; ++j)
                if(bit(i, j)) crt *= v[j];
            if(nrbit[i] & 1)
                impar.pb(crt);
            else par.pb(crt);
        }
    
    while(st <= dr)
    {
        m = aux = (st + dr) >> 1;

        for(vector<int> :: iterator it = par.begin(); it != par.end(); ++it)
            aux += m/(*it);
        for(vector<int> :: iterator it = impar.begin(); it != impar.end(); ++it)
            aux -= m/(*it);

        if(aux == p && cmmdc(n, m) == 1)
        {
            printf("%lld\n", m);
            return 0;
        }
        else if(aux >= p)
            dr = m-1;
        else
            st = m+1;
    }
    return 0;
}