Cod sursa(job #1740642)

Utilizator sulzandreiandrei sulzandrei Data 11 august 2016 22:23:34
Problema Principiul includerii si excluderii Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 3.18 kb
#include <iostream>
#include <fstream>
#define ull unsigned long long int
using namespace std;
ifstream in("pinex.in");
ofstream out("pinex.out");

struct Combinare
{
    int n,p;
    bool as,ev;
    Combinare(int a, int b):n(a),p(b){};
    void valid(int k, int *v, bool &ev)
    {
        int i;
        ev = true;
        if( k > 0 && v[k]<=v[k-1])
            ev = false;
    };
    void init( int k, int  *v)
    {
        v[k] = 0;
    };
    void suc(int k, int v[], bool &as)
    {
        if( v[k]< n-p+k+1)
        {
            v[k]++;
            as = true;
        }
        else
            as = false;

    };
    int* vectorSolutie(int k, int v[])
    {
        int * comb = new int[k+1];
        for(int i = 0 ; i < p; i ++)
            comb[i] = v[i] ;
        return comb;
    };
    bool solutie(int k)
    {
        if(k == p-1)
            return true;
        return false;
    };
    int ** Cnp(int & nrofCnp)
    {
        nrofCnp = 0;
        int ** combinari = new int*[(1<< n)+4];

        int v[n];
        int k = 0;
        init(k,v);
        while( k>-1 )
        {
            do
            {
                suc(k,v,as);

                if(as)
                    valid(k,v,ev);
            }
            while( as  && !(as && ev));
            if (as)
                if(solutie(k))
                    combinari[++nrofCnp] = vectorSolutie(k,v);
                else
                {
                    k++;
                    init(k,v);
                }
            else
                k--;
        }
        return combinari;
    };
};
int * primeDivisors(ull n, ull &nr)//O(sqrt(n)) complexitate
{
    int * prime = new int[100];
    nr = 0;
    for(ull i = 2 ; n > 1; i++)//we go just to sqrt(n) and while we have prime divisors to search
        if(n%i == 0)
        {
            while(n%i == 0)
                n/=i;
            prime[++nr] = i;
        }
    return prime;
}
ull solve2(ull a, ull b)
{
    ull nr ;
    int * d = primeDivisors(b,nr);
    ull sum = 0;
    ull prod = 1;
    for(int i = 1 ; i <= nr ; i ++)
    {
        sum += a/d[i];
        prod *= d[i];
    }
    if(nr >1)
        if(nr%2 ==0 )
            sum -= a/prod;
        else
            sum += a/prod;
    for(int i = 2 ; i < nr ; i ++)
    {
        Combinare c(nr,i);
        int com;
        int ** sol = c.Cnp(com);
        for(int j = 1 ; j <= com ; j++)
        {
            prod = 1;
            for(int k = 0 ; k < i ; k++)
                prod *= d[sol[j][k]];
            sum += ((a/prod) * ((i % 2 ==0)?-1:1));
            delete []sol[j];
        }
        delete []sol;
    }
    return a - sum;

}
ull gcd(ull a , ull b);
ull solve1(ull a, ull b);
int main()
{
    ull m,a,b;
    in >> m;
    while(m--)
    {
        in >> a >> b;
        out << solve2(a,b) << '\n';
    }
    return 0;
}
ull solve1(ull a, ull b)
{
    ull nr = 0;
    for(ull i = 1 ; i <= a ; i ++)
        if(gcd(i,b) == 1)
            nr++;
    return nr;
}
ull gcd(ull a , ull b)
{
    ull r;
    while(b)
    {
        r = a%b;
        a = b;
        b = r;
    }
    return a;
}