Cod sursa(job #1996205)

Utilizator laurageorgescuLaura Georgescu laurageorgescu Data 30 iunie 2017 15:48:00
Problema Vanatoare Scor 25
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.86 kb
#include <fstream>
#include <vector>

using namespace std;

ifstream fin ("vanatoare.in"); ofstream fout ("vanatoare.out");

typedef long long i64;

const int nmax = 16;
const int inf = 1 << 30;

struct str {
    int a, b;
} v[nmax + 1];

str c[(1 << nmax)];
int ok[(1 << nmax)];
int d[(1 << nmax)], vine[(1 << nmax)];

int m;
int cn[nmax + 1];
vector< int > st;

int gcd (int a, int b) {
    while (b > 0) {
        int r = a % b;
        a = b;
        b = r;
    }
    return a;
}

void bck (int stn, int pos) {
    if (stn != 0) st.push_back( stn );

    for (int i = pos; i < m; ++ i) {
        bck(stn + (1 << cn[ i ]), i + 1);
    }
}

void eeuclid (int a, int b, int &x, int &y, int &sol) {
    if (b == 0) {
        x = 1;
        y = 0;
        sol = a;
        return ;
    }

    i64 cat = a / b;
    eeuclid(b, a % b, x, y, sol);
    i64 xx, yy;
    xx = y;
    yy = x - cat * xx;
    x = xx, y = yy;
}

int main() {
    int n, t;
    fin >> n >> t;
    for (int i = 0; i < n; ++ i) {
        fin >> v[ i ].b >> v[ i ].a;
        c[1 << i] = v[ i ];
        ok[1 << i] = v[ i ].b;
    }

    for (int i = 1; i < (1 << n); ++ i) {
        int u = 0;
        for (int j = 0; j < n; ++ j) {
            if (i & (1 << j)) {
                u = j; break;
            }
        }

        int j = i - (1 << u);
        if (j == 0) continue;
        ok[ i ] = -1;
        if (ok[ j ] == -1) continue;

        int cja = c[ j ].a, vua = v[ u ].a, cjb = c[ j ].b, vub = v[ u ].b;

        if (cja > t) {
            if (cjb % vua == vub) {
                ok[ i ] = cjb;
            }
            c[ i ] = c[ j ];
        } else {
            int D = gcd(cja, vua);

            int p, q, ans, ct = vub - cjb;
            eeuclid(cja, vua, p, q, ans);

            if (ct % ans == 0) {
                p *= (ct / ans);
                q *= (ct / ans);

                i64 k = 1LL * cja * vua / D;

                i64 loc = cja * p + cjb;
                loc %= k;
                if (loc < 0) loc += k;

                if (k <= t) c[ i ].a = k;
                else        c[ i ].a = t + 1;

                if (loc <= t) {
                    ok[ i ] = loc;
                    c[ i ].b = loc;
                }
            }
        }
    }

    d[ 0 ] = 0;
    for (int i = 1; i < (1 << n); ++ i) {
        m = 0;
        for (int j = 0; j < n; ++ j) {
            if (i & (1 << j))
                cn[ m ++ ] = j;
        }

        st.clear();
        bck(0, 0);

        d[ i ] = inf;
        for (auto j : st) {
            if (ok[ j ] != -1 && d[i - j] + 1 < d[ i ]) {
                d[ i ] = d[i - j] + 1;
                vine[ i ] = i - j;
            }
        }
    }

    fout << d[(1 << n) - 1] << "\n";
    int stn = (1 << n) - 1;

    while (stn != 0) {
        fout << ok[stn - vine[stn]] << " ";
        stn = vine[ stn ];
    }
    fout << "\n";

    fin.close();
    fout.close();
    return 0;
}