Cod sursa(job #2232886)

Utilizator robx12lnLinca Robert robx12ln Data 21 august 2018 16:02:05
Problema Vanatoare Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.17 kb
#include<bits/stdc++.h>
using namespace std;
ifstream fin("vanatoare.in");
ofstream fout("vanatoare.out");
int N, T, Dp[1<<17], G[1<<17];
pair<int,int> V[20], Cross[1<<17];


int euclid( int a, int b, long long &x, long long &y ){
    if( b == 0 ){
        x = 1;
        y = 0;
        return a;
    }else{
        long long x0, y0;
        int gcd = euclid( b, a % b, x0, y0 );
        y = x0 - 1LL * (a / b) * y0;
        x = y0;
        return gcd;
    }
}

inline pair<int,int> solve( pair<int,int> A, pair<int,int> B ){

    if( A.second > T && B.second > T ){
        if( A.first == B.first )
            return make_pair( A.first, T + 1 );
        else
            return make_pair( -1, 0 );
    }

    if( A.second > T || B.second > T ){
        if( A.second > T ){
            if( ( A.first - B.first ) % B.second == 0 )
                return make_pair( A.first, T + 1 );
            else
                return make_pair( -1, 0 );
        }
        if( B.second > T ){
            if( ( B.first - A.first ) % A.second == 0 )
                return make_pair( B.first, T + 1 );
            else
                return make_pair( -1, 0 );
        }
    }

    long long t1, t2;
    int gcd = euclid( A.second, B.second, t1, t2 );

    long long h = 1LL * A.second / gcd * B.second;

    if( (B.first - A.first) % gcd != 0 )
        return make_pair( -1, 0 );

    int L = ( B.first - A.first ) / gcd;
    int m1 = (1LL * t1 * L) % ( B.second / gcd );
    if( m1 < 0 )
        m1 += ( B.second / gcd );
    long long x = ( 1LL * A.second * m1 + A.first ) % h;
    if( x < 0 )
        x += h;

    if( x <= 1LL * T ){
        if( h <= 1LL * T )
            return make_pair( (int)x, (int)h );
        else
            return make_pair( (int)x, T + 1  );
    }
    return make_pair( -1, 0 );

}

int main(){
    fin >> N >> T;
    for( int i = 0; i < N; i++ )
        fin >> V[i].first >> V[i].second;

    for( int mask = 1; mask < (1<<N); mask++ ){

        int nr = 0, bit;
        for( int i = N - 1; i >= 0; i-- )
            if( ( ( mask>>i ) & 1 ) == 1 )
                nr++, bit = i;

        if( nr == 1 ){
            if( V[bit].first <= T )
                Cross[mask] = V[bit];
            else
                Cross[mask] = { -1, 0 };
            continue;
        }

        if( Cross[mask ^ (1<<bit)].first == -1 ){
            Cross[mask] = Cross[mask ^ (1<<bit)];
            continue;
        }

        if( V[bit].first > T ){
            Cross[mask] = { -1, 0 };
            continue;
        }

        Cross[mask] = solve( V[bit], Cross[mask ^ (1<<bit)] );

    }

    for( int mask = 1; mask < (1<<N); mask++ ){

        Dp[mask] = 20;

        for( int conf = mask; conf != 0; conf = ( (conf - 1) & mask ) ){
            if( Cross[conf].first != -1 && Dp[mask] > Dp[mask ^ conf] + 1 ){
                Dp[mask] = Dp[mask ^ conf] + 1;
                G[mask] = conf;
            }
        }

    }

    fout << Dp[(1<<N) - 1] << "\n";

    int mask = (1<<N) - 1;
    while( mask != 0 ){
        fout << Cross[ G[mask] ].first << " ";
        mask = (mask ^ G[mask]);
    }

    return 0;
}