Cod sursa(job #2083262)

Utilizator VoineaAndreiVoinea Ioan-Andrei VoineaAndrei Data 7 decembrie 2017 14:26:50
Problema Frac Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.82 kb
#include<bits/stdc++.h>
using namespace std;

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

long long n,p;
vector<int>v;

//descompune numitorul in factori primi in v
void desc_fact_primi(long long n){
    if(n%2==0)v.push_back(2);
    while(n%2==0) n/=2;

    long long i=3;
    while(n>1){
        if(n%i==0) v.push_back(i);
        while(n%i==0) n/=i;
        i+=2;
    }
}

//returneaza al x-lea numar care este prim cu n
long long prim(long long x){
    long long sol=0;
    for(int i=0;i<(1<<v.size());++i){
            long long prod=1,semn=1;
            for(int j=0;j<v.size();++j)
                if(i&(1<<j)){
                        prod*=v[j];
                        semn*=-1;
                    }
            sol+=x/prod*semn;
        }
    return sol;
}

//cautare binara pentru eficienta
//cauta numarul prim cu n de pe pozitia p
long long cautare_binara(long long x){
    long long s=0,d=n-1,last_poz=-1;

    while(s<=d){

        long long mij=(d-s)/2+s;

        long long median=prim(mij);
        if(median<p) {
                s=mij+1;continue;
            }
        else if(median>p) {
                d=mij-1;continue;
            }

        last_poz=mij;
        d=mij-1;
    }
    return last_poz;
}

//calculeaza cate numere intre 1 si n sunt prime cu n (secventa farey)
long long nediv(long long x){
    for(unsigned int i=0;i<v.size();++i){
        x/=v[i];
        x*=v[i]-1;
    }
    return x;
}

int main(){
    f>>n>>p;
    desc_fact_primi(n);

    long long nr_nedivizori=nediv(n);
    long long interval;

    if(p%nr_nedivizori==0) //daca p este la inceput de interval
        {g<<n*p/nr_nedivizori-1<<'\n';return 0;}

    interval=p/nr_nedivizori;
    p%=nr_nedivizori;
    long long rez=cautare_binara(n);

    g<<interval*n+rez<<'\n';
}