Cod sursa(job #163649)

Utilizator mariusdrgdragus marius mariusdrg Data 22 martie 2008 14:51:41
Problema Vanatoare Scor 25
Compilator cpp Status done
Runda preONI 2008, Runda Finala, Clasele 11-12 Marime 3.01 kb
#include<stdio.h>
#include<algorithm>
#include<set>
#define LL long long
#define mkp make_pair

using namespace std;

const int maxst = (1 << 17);
const int INF = 2000000000;
const int maxn = 30;

LL A[3],B[3],CAUX[3];
int REM[maxst],E[maxst];
LL V[maxn],C[maxn];
int N,T;
LL mod(LL a){return a > 0 ? a : -a;}

LL gcd(LL a,LL b)
{
        A[0] = 1;
        A[1] = 0;
        B[0] = 0;
        B[1] = 1;
        while(b)
        {
                CAUX[0] = A[0] - B[0] * (a / b);
                CAUX[1] = A[1] - B[1] * (a / b);
                A[0] = B[0];A[1] = B[1];B[0] = CAUX[0];B[1] = CAUX[1];
                LL c = a % b;
                a = b;
                b = c;
        }
        return a;
}

LL ver(int conf)
{
        pair <LL,LL> cur = mkp(0,1);
        for(int j = 0;(1 << j) <= conf; ++j)
        {
                if (((1 << j) & conf) == 0) continue;
                int i = j + 1;
                //mai bagi gcd ca sa afli intersectia
                LL l = gcd(cur.second,V[i]);
                if (mod(cur.first - C[i]) % l != 0) return INF;
                if (cur.first > C[i]) A[0] *= -1;
                        else A[1] *= -1;
                A[0] *= mod(cur.first - C[i]) / l;
                A[1] *= mod(cur.first - C[i]) / l;
            //    A[0] = mod(A[0]);
                A[0] = A[0] > 0 ? A[0] * cur.second + cur.first: A[1] * V[i] + C[i];
                LL mul = cur.second * V[i] / l;
                A[0] = A[0] - mul * (A[0] / mul);
                LL p = 1;
                LL x = 0;
                LL poz = max(cur.first,C[i]);
                for(;p <= 200000000;p <<= 1);
                for(;p;p >>= 1)
                        if ((x + p) * mul + A[0] < poz) x += p;
                if (A[0] + x * mul < poz)x++;
                A[0] += x * mul;
                LL inter = A[0];
                if (inter > T) return INF;
                cur = mkp(inter,cur.second * V[i] / l );
        }
        return cur.first;
}

int calc(int conf)
{
        if (ver(conf) <= T)
        {
                E[conf] = 1;
                REM[conf] = conf;
        }
        if (E[conf]) return E[conf];
        int rez = INF;
        for(int i = 1;i < conf; ++i)
        {
                if (((i & conf) == i)&& ver(i) <= T)
                {
                        int x = calc(conf ^ i) + 1;
                        if (x < rez)
                        {
                                rez = x;
                                REM[conf] = i;
                        }
                }

        }
        E[conf] = rez;
        return rez;
}



int main()
{
        freopen("vanatoare.in","r",stdin);
        freopen("vanatoare.out","w",stdout);
        scanf("%d %d",&N,&T);
 //       printf("%d\n",sizeof(REM) + sizeof(E));
        for(int i = 1;i <= N; ++i)
        {
                scanf("%d %d",&C[i],&V[i]);
        }
        printf("%d\n",calc((1 << N) - 1));
        int cur = (1 << N) - 1;
        while(cur)
        {
                printf("%d ",ver(REM[cur]));
                cur ^= REM[cur];
        }
        return 0;
}