Cod sursa(job #627126)

Utilizator cristianalex81Cristian Alexandru cristianalex81 Data 29 octombrie 2011 05:35:48
Problema Frac Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.24 kb
#include <stdio.h>
#include <math.h>
#include <vector>
#define dim 10000002 //square root of 10^14;
#define max_u64 0xffffffffffffffff //max value for unsigned 64 bit
using namespace std;

typedef unsigned long long uint64;
typedef unsigned int uint32;

uint64 n,p,rez;
bool noprnr[dim];
vector <uint64> fprim;
vector <uint32> prim;
vector <uint32> stack;
vector <uint64> num;

void get_prim()
{
    uint32 i,j;
    noprnr[0]=true;
    noprnr[1]=true;
    prim.push_back(2);
    uint32 sq = sqrt(n) + 1;
    for (i=3;i<sq;i+=2)
    {
        if (noprnr[i]==false)
        {
            prim.push_back(i);
            for(j=2*i;j<sq;j+=i)
                noprnr[j]=true;
        }
        noprnr[i+1]=false;
    }
}

void get_fprim()
{
    uint32 i;
    for (i=0;((i<prim.size())&(n>1));i++)
    {
        if (n%prim[i]==0)//prime factor
        {
            fprim.push_back(prim[i]);
            while (n%prim[i]==0)//eliminate prim[i]
                n/=prim[i];
        }
    }
    if (n>1)//p is prime
        fprim.push_back(n);
}
void fill(int level, int index)
{
    uint32 i;
    for (i=index;i<fprim.size();i++)
    {
        if (level==0)
            stack.push_back(fprim[i]);
        else
            stack.push_back(fprim[i]*stack[level-1]);

        num.push_back(stack[level]);
        fill(level+1,i+1);
        stack.pop_back();
    }
}

void calculate(uint64 x)
{
    rez=0;
    uint32 i;
    for (i=0;i<num.size();i++)
        if(i%2==0)
            rez+=x/num[i];
        else
            rez-=x/num[i];
    rez = x - rez;
}

uint64 search()
{
    uint64 l=0,m,r=max_u64;
    get_prim();
    get_fprim();
    prim.clear();
    fill(0,0);
    fprim.clear();
    while (l<=r)
    {
        m = (l+r)>>1;
        calculate(m);
        if (rez == p)
        {
            do
            {
                m--;
                calculate(m);
            }while (rez==p);
            return m+1;
        }
        else
        {
            if (rez>p)//have to reduce upper bound;
                r=m+1;
            else      //have to increase lower bound;
                l=m-1;
        }
    }
    return -1;
}

int main()
{
    freopen("frac.in","r",stdin);
    freopen("frac.out","w",stdout);
    scanf("%lld %lld",&n,&p);
    printf("%lld\n",search());
    return 0;
}