Cod sursa(job #123237)

Utilizator peanutzAndrei Homorodean peanutz Data 15 ianuarie 2008 00:20:36
Problema Frac Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.94 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); }

long long cmmdc(long long a, long long b)
{
    if(a < b)
	{
	   long long aux=a;
	   a=b;
	   b=aux;
	}
    while(b)
	{
	   long long r=a%b;
	   a=b;
	   b=r;
	}
    return a;
}

short nrbit[132000];

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 = (long long)(1<<30)*(1<<30)*2, m, crt, aux = n;
    vector<long long> v;
    long long 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<long long> par, impar;

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

        for(vector<long long> :: iterator it = par.begin(); it != par.end(); ++it)
            aux += m/(*it);
        for(vector<long long> :: 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;
}