Cod sursa(job #164653)

Utilizator filipbFilip Cristian Buruiana filipb Data 24 martie 2008 17:30:30
Problema Vanatoare Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.08 kb
#include <stdio.h>
#include <algorithm>

using namespace std;

#define ll long long

typedef struct { int cc, vv; } mistret;

int N, T, c[32], v[32], bst;
int config, st[32], SOL[32];
short int opt[1<<16]; int TIMP[1<<16], prev[1<<16], w[1<<16];
mistret M[32];

int cmp_mistret(const mistret& a, const mistret& b)
{
    return a.vv > b.vv;
}

int bit(int X, int nr_bit)
{ return (X & (1<<nr_bit)) != 0; }

int gcd(int a, int b)
{ return (b == 0 ? a : gcd(b, a%b)); }

void gcd_extins(int a, int b, ll &X, ll &Y)
{
    ll xp, yp;

    if (b == 0)
        X = 1, Y = 0;
    else
    {
        gcd_extins(b, a%b, xp, yp);
        X = yp; Y = xp - (ll)(a/b) * yp;
    }
}

void preproc(void)
{
    int i, j, d, conf, A, B, D;
    ll X, Y;

    for (i = 1; i < (1<<N); ++i)
    {            
        for (j = N-1; j >= 0; --j)
            if (bit(i, j))
                break;

        conf = i - (1<<j);
        if (!conf)
        {
            TIMP[i] = c[j];
            w[i] = v[j];
            continue;
        }
        
        if ((w[conf] > T && TIMP[conf] % v[j] != c[j]) || TIMP[conf] > T)
        {
            TIMP[i] = T+1; // nu am solutie
            continue;
        }

        A = w[conf] % v[j];
        B = c[j] - TIMP[conf] % v[j];
        if (B < 0) B += v[j];

        D = gcd(A, v[j]);
        if (B % D)
        {
            TIMP[i] = T+1; // nu am solutie
            continue;
        }
        gcd_extins(A, v[j], X, Y);
        X = (X * (B/D)) % v[j];
        if (X < 0) X += v[j];
        // X este o solutie. Solutiile sunt de forma X + K * (v[j]/D)
        X %= (v[j]/D); // aceasta este solutia minima

        if ((ll)TIMP[conf] + (ll)X * w[conf] > T)
        {
            TIMP[i] = T+1; // nu am solutie
            continue;
        }
        TIMP[i] = TIMP[conf] + X * w[conf];

        // actualizam cmmmc
        d = gcd(w[conf], v[j]);
        if ((ll)w[conf] * (v[j] / d) > T)
            w[i] = T+1;
        else
            w[i] = w[conf] * (v[j] / d);
    }
}

void back(int nivel, int new_conf)
{
    if (nivel == N)
    {
        if (1 + opt[config-new_conf] < opt[config])
            opt[config] = 1 + opt[config-new_conf],
            prev[config] = config-new_conf,
            w[config] = TIMP[new_conf];
        return ;
    }

    st[nivel] = 0; back(nivel+1, new_conf);
    if (bit(config, nivel) && TIMP[new_conf + (1<<nivel)] <= T)
    {
        st[nivel] = 1;
        back(nivel+1, new_conf + (1<<nivel));
    }
    
}

int main(void)
{
    int i;
    
    freopen("vanatoare.in", "r", stdin);
    freopen("vanatoare.out", "w", stdout);
    
    scanf("%d %d", &N, &T);
    for (i = 0; i < N; ++i)
        scanf("%d %d", &M[i].cc, &M[i].vv);
    sort(M, M+N, cmp_mistret);
    for (i = 0; i < N; i++)
        c[i] = M[i].cc, v[i] = M[i].vv;
    
    preproc();
        
    for (config = 1; config < (1<<N); ++config)
    {
        opt[config] = 122;
        back(0, 0);
    }

    printf("%d\n", opt[(1<<N)-1]);
    for (i = (1<<N)-1; i; i = prev[i])
        SOL[++bst] = w[i];

    for (i = 1; i < bst; ++i)
        printf("%d ", SOL[i]);
    printf("%d\n", SOL[bst]);
    
    return 0;
}