Problem:
Score : 800 points

Problem Statement

There are N stores called Store 1, Store 2, \cdots, Store N. Takahashi, who is at his house at time 0, is planning to visit some of these stores.

It takes Takahashi one unit of time to travel from his house to one of the stores, or between any two stores.

If Takahashi reaches Store i at time t, he can do shopping there after standing in a queue for a_i \times t + b_i units of time. (We assume that it takes no time other than waiting.)

All the stores close at time T + 0.5. If Takahashi is standing in a queue for some store then, he cannot do shopping there.

Takahashi does not do shopping more than once in the same store.

Find the maximum number of times he can do shopping before time T + 0.5.

Constraints

All values in input are integers.

1 \leq N \leq 2 \times 10^5

0 \leq a_i \leq 10^9

0 \leq b_i \leq 10^9

0 \leq T \leq 10^9

Input

Input is given from Standard Input in the following format:

N T
a_1 b_1
a_2 b_2
\vdots
a_N b_N

Output

Print the answer.

Sample Input 1

3 7
2 0
3 2
0 3

Sample Output 1

2

Here is one possible way to visit stores:

From time 0 to time 1: in 1 unit of time, he travels from his house to Store 1.

From time 1 to time 3: for 2 units of time, he stands in a queue for Store 1 to do shopping.

From time 3 to time 4: in 1 unit of time, he travels from Store 1 to Store 3.

From time 4 to time 7: for 3 units of time, he stands in a queue for Store 3 to do shopping.

In this way, he can do shopping twice before time 7.5.

Sample Input 2

1 3
0 3

Sample Output 2

0

Sample Input 3

5 21600
2 14
3 22
1 3
1 10
1 9

Sample Output 3

5

Sample Input 4

7 57
0 25
3 10
2 4
5 15
3 22
2 14
1 15

Sample Output 4

3

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Linq;
using System.Collections.Generic;

namespace Contest
{
    class Program
    {
        static void Main(string[] args)
        {
            HitachiD();
        }
        static void HitachiA()
        {
            var s = ReadStr();
            if (s.Length % 2 == 1) { Console.WriteLine("No");return; }
            for(int i = 0; i < s.Length; ++i)
            {
                if (s[i] != (i%2 == 0 ? 'h' : 'i'))
                {
                    Console.WriteLine("No"); return;
                }
            }
            Console.WriteLine("Yes");
        }
        static void HitachiB()
        {
            var abm = ReadIntN();
            var A = abm[0];
            var B = abm[1];
            var M = abm[2];
            var a = ReadIntN();
            var b = ReadIntN();
            var xyc = new List<int[]>();
            for(int i = 0; i < M; ++i)
            {
                xyc.Add(ReadIntN());
            }
            var naive = a.Min() + b.Min();
            foreach(var cpn in xyc)
            {
                var v = a[cpn[0]-1] + b[cpn[1]-1] - cpn[2];
                naive = Math.Min(naive, v);
            }
            Console.WriteLine(naive);
        }
        static void HitachiC()
        {
            var N = ReadInt();
            var Adj = ReadAdjacencyList(N, N - 1);

            var dist = new int[N + 1];
            dist[1] = 0;
            List<int> list = new List<int>();
            bool[] check = new bool[N + 1];
            check[1] = true;
            list.Add(1);
            int current = 1;
            while (list.Count > 0)
            {
                var next = new List<int>();
                foreach(var v in list)
                {
                    foreach(var w in Adj[v])
                    {
                        if (!check[w])
                        {
                            check[w] = true;
                            dist[w] = current;
                            next.Add(w);
                        }
                    }
                }
                current++;
                list = next;
            }
            var mod = new int[] { 0, 1, 2, 0, 2, 1 };
            var count = new int[3];
            for(int i = 1; i <= N; ++i)
            {
                count[mod[dist[i] % 6]]++;
            }
            var order = Enumerable.Range(0, 3).OrderBy(i => count[i]).ToArray();
            var place = new int[N + 1];
            int m1 = 1;
            int m2 = 2;
            int m0 = 3;
            if (count[order[2]] > N * 2 / 3)
            {
                for (int i = 1; i <= N; ++i)
                {
                    var x = mod[mod[dist[i] % 6]];
                    if (order[2] == x)
                    {
                        if (m1 > N)
                        {
                            if (m2 > N)
                            {
                                place[i] = m0; m0 += 3;
                            }
                            else
                            {
                                place[i] = m2; m2 += 3;
                            }
                        }
                        else
                        {
                            place[i] = m1; m1 += 3;
                        }
                    }
                    else
                    {
                        place[i] = m0; m0 += 3;
                    }
                }
            }
            else
            {
                for (int i = 1; i <= N; ++i)
                {
                    var x = mod[mod[dist[i] % 6]];
                    if (order[2] == x)
                    {
                        if (m1 > N)
                        {
                            place[i] = m0; m0 += 3;
                        }
                        else
                        {
                            place[i] = m1; m1 += 3;
                        }
                    }
                    else if (order[1] == x)
                    {
                        if (m2 > N)
                        {
                            place[i] = m0; m0 += 3;
                        }
                        else
                        {
                            place[i] = m2; m2 += 3;
                        }
                    }
                    else
                    {
                        place[i] = m0; m0 += 3;
                    }
                }
            }
            var ans = new int[N];
            bool ok = true;
            for(int i = 1; i <= N; ++i)
            {
                if (place[i] > N)
                {
                    ok = false;
                    break;
                }
                ans[place[i] - 1] = i;
            }
            if (ok)
            {
                Console.WriteLine(String.Join(" ", ans));
            }
            else
            {
                Console.WriteLine(-1);
            }
        }
        static void HitachiD()
        {
            var nt = ReadLongN();
            var N = nt[0];
            var T = nt[1];
            var AB = ReadTupleLong((int)N);

            AB = AB.OrderBy(x => -x.Item1 * 1000000000 - x.Item2).ToArray();
            long[] time = Enumerable.Range(0, (int)N + 1).Select(i => 1000000000000).ToArray();
            time[0] = 0;
            int maxj = 0;
            for(int i = 0; i < N; ++i)
            {
                var ab = AB[i];
                if (ab.Item1 == 0) { break; }
                for(int j = maxj; j >=0 ; --j)
                {
                    if(time[j]>= 1000000000000) { break; }
                    var t = (time[j] + 1) * (ab.Item1 + 1) + ab.Item2;
                    if (t <= T)
                    {
                        time[j + 1] = Math.Min(time[j + 1], t);
                        maxj = Math.Max(j + 1, maxj);
                    }
                }
            }
            var bs = new List<long>();
            foreach(var ab in AB)
            {
                if (ab.Item1 == 0)
                {
                    bs.Add(ab.Item2);
                }
            }
            bs.OrderBy(x => x).ToList();
            long max = maxj;
            for(int i = 0; i < N; ++i)
            {
                if(time[i]>= 1000000000000) { break; }
                for(int j = 0; j < bs.Count; ++j)
                {
                    var t = time[i] + 1 + bs[j];
                    if (t <= T)
                    {
                        time[i] = t;
                        max = Math.Max(max, i + j + 1);
                    }
                    else
                    {
                        break;
                    }
                }
            }
            Console.WriteLine(max);
        }
        static void HitachiE()
        {

        }


        class Util
        {
            public static readonly long P = 1000000007;

            public static long Sum(long[] array)
            {
                return Sum(array, array.Length);
            }
            public static long Sum(long[] array, int n)
            {
                long total = 0;
                for(int i = 0; i < n; ++i)
                {
                    total += array[i];
                }
                return total;
            }
            public static long Count(long[] array, long x)
            {
                return Count(array, x, array.Length);
            }
            public static long Count(long[] array, long x, int n)
            {
                long total = 0;
                for (int i = 0; i < n; ++i)
                {
                    total += (array[i] == x ? 1 : 0);
                }
                return total;
            }
            public static long[] ASum(long[] array)
            {
                var res = new long[array.Length + 1];
                for (int i = 0; i < array.Length; ++i)
                {
                    res[i + 1] = res[i] + array[i];
                }
                return res;
            }
            public static long[] ASum(long[] array, long P)
            {
                var res = new long[array.Length + 1];
                for (int i = 0; i < array.Length; ++i)
                {
                    res[i + 1] = (res[i] + array[i]) % P;
                }
                return res;
            }

            public static long GCD(long a, long b)
            {
                while (b > 0)
                {
                    var c = a % b;
                    a = b;
                    b = c;
                }
                return a;
            }
            public static bool IsPrime(long x)
            {
                var fact = Factorize(x);
                return fact.Count == 1 && fact.Values.ElementAt(0) == 1;
            }
            public static Dictionary<long,int> Factorize(long x)
            {
                var dict = new Dictionary<long, int>();
                long minp = 2;
                while (x > 1)
                {
                    bool ok = false;
                    for(long p = minp; p * p <= x; ++p)
                    {
                        if (x % p == 0)
                        {
                            if (!dict.ContainsKey(p))
                            {
                                dict.Add(p, 0);
                            }
                            dict[p]++;
                            minp = p;
                            x /= p;
                            ok = true;
                            break;
                        }
                    }
                    if (!ok)
                    {
                        if (!dict.ContainsKey(x)) { dict.Add(x, 0); }
                        dict[x]++;
                        break;
                    }
                }
                return dict;
            }
            public static long Inverse(long a, long p)
            {
                long b = p, c = 1, d = 0, e = 0, f = 0;
                while (b != 0)
                {
                    e = a / b;
                    f = b; b = a - e * b; a = f;
                    f = d; d = c - e * d; c = f;
                }
                c %= p;
                return c + (c < 0 ? p : 0);
            }
            public static long[] Facts(int n, long p)
            {
                var facts = new long[n + 1];
                facts[0] = 1;
                for (int i = 1; i <= n; ++i)
                {
                    facts[i] = (i * facts[i - 1]) % p;
                }
                return facts;
            }
            public static Func<int,int,long> Combin(int n, long P)
            {
                var fact = Facts(n, P);
                var inv = fact.Select(x => Inverse(x, P)).ToArray();
                return (N, M) =>
                {
                    if (N < 0 || N < M || M < 0) { return 0; }
                    return (((fact[N] * inv[M]) % P) * inv[N - M]) % P;
                };
            }

            /// <summary>
            /// Calc Combin(n,m) where n is large and m<=mMax
            /// </summary>
            public static Func<int,int,long> CombinLarge(int mMax, long p)
            {
                var inv = Enumerable.Range(0, mMax + 1).Select(x => Util.Inverse(x, Util.P)).ToArray();
                return (n, m) =>
                {
                    long mult = 1;
                    for (int i = 1; i <= m; ++i)
                    {
                        mult = (((mult * (n + 1 - i)) % Util.P) * inv[i]) % Util.P;
                    }
                    return mult;
                };
            }

            /// <summary>
            /// Calc 2^n mod p
            /// </summary>
            public static long Power2(long n, long p)
            {
                return Power(2, n, p);
            }
            public static long Power(long a, long n, long p)
            {
                long res = 1;
                long mult = a;
                for (int i = 0; i < 40; ++i)
                {
                    if ((n & ((long)1 << i)) > 0)
                    {
                        res = (res * mult) % p;
                    }
                    mult = (mult * mult) % p;
                }
                return res;
            }

            public static int Lowerbound<T1,T2>(SortedList<T1,T2> list, T1 x) where T1 : IComparable<T1>
            {
                return Lowerbound(list.Keys, x);
            }
            public static int Upperbound<T1, T2>(SortedList<T1, T2> list, T1 x) where T1 : IComparable<T1>
            {
                return Upperbound(list.Keys, x);
            }
            public static int Lowerbound<T>(IList<T> list, T x) where T : IComparable<T>
            {
                int min = 0;
                int max = list.Count;
                while (min < max)
                {
                    var mid = (min + max) / 2;
                    if (list[mid].CompareTo(x) >= 0)
                    {
                        max = mid;
                    }
                    else
                    {
                        min = mid + 1;
                    }
                }
                return max;
            }
            public static int Upperbound<T>(IList<T> list, T x) where T : IComparable<T>
            {
                int min = 0;
                int max = list.Count;
                while (min < max)
                {
                    var mid = (min + max) / 2;
                    if (list[mid].CompareTo(x) > 0)
                    {
                        max = mid;
                    }
                    else
                    {
                        min = mid + 1;
                    }
                }
                return max;
            }
            /// <summary>
            /// Thanks to yambe2002-san
            /// </summary>
            public class BST<T> where T : IComparable
            {
                public class Node
                {
                    public T V;
                    public Node L, R;
                    public int Count;
                    public Node(T v) { V = v; Count = 1; }
                }
                static Random _rnd = new Random();
                public static int Count(Node t) { return t == null ? 0 : t.Count; }
                static Node Update(Node t) { t.Count = Count(t.L) + Count(t.R) + 1; return t; }
                public static Node Merge(Node l, Node r)
                {
                    if (l == null || r == null) return l == null ? r : l;
                    if ((double)Count(l) / (double)(Count(l) + Count(r)) > _rnd.NextDouble())
                    { l.R = Merge(l.R, r); return Update(l); }
                    else { r.L = Merge(l, r.L); return Update(r); }
                }
                public static Tuple<Node, Node> Split(Node t, int k)
                {
                    if (t == null) return new Tuple<Node, Node>(null, null);
                    if (k <= Count(t.L))
                    {
                        var s = Split(t.L, k);
                        t.L = s.Item2;
                        return new Tuple<Node, Node>(s.Item1, Update(t));
                    }
                    else
                    {
                        var s = Split(t.R, k - Count(t.L) - 1);
                        t.R = s.Item1;
                        return new Tuple<Node, Node>(Update(t), s.Item2);
                    }
                }
                public static Node Remove(Node t, T v)
                {
                    if (Find(t, v) == null) return t;
                    return RemoveAt(t, LowerBound(t, v));
                }
                public static Node RemoveAt(Node t, int k)
                {
                    var s = Split(t, k);
                    var s2 = Split(s.Item2, 1);
                    return Merge(s.Item1, s2.Item2);
                }
                public static bool Contains(Node t, T v) { return Find(t, v) != null; }
                public static Node Find(Node t, T v)
                {
                    while (t != null)
                    {
                        var cmp = t.V.CompareTo(v);
                        if (cmp > 0) t = t.L;
                        else if (cmp < 0) t = t.R;
                        else break;
                    }
                    return t;
                }

                public static Node FindByIndex(Node t, int idx)
                {
                    if (t == null) return null;
                    var currentIdx = Count(t) - Count(t.R) - 1;
                    while (t != null)
                    {
                        if (currentIdx == idx) return t;
                        if (currentIdx > idx)
                        { t = t.L; currentIdx -= (Count(t == null ? null : t.R) + 1); }
                        else { t = t.R; currentIdx += (Count(t == null ? null : t.L) + 1); }
                    }
                    return null;
                }
                public static int UpperBound(Node t, T v)
                {
                    var torg = t;
                    if (t == null) return -1;

                    var ret = Int32.MaxValue;
                    var idx = Count(t) - Count(t.R) - 1;
                    while (t != null)
                    {
                        var cmp = t.V.CompareTo(v);

                        if (cmp > 0)
                        {
                            ret = Math.Min(ret, idx);
                            t = t.L;
                            idx -= (Count(t == null ? null : t.R) + 1);
                        }
                        else if (cmp <= 0)
                        {
                            t = t.R;
                            idx += (Count(t == null ? null : t.L) + 1);
                        }
                    }
                    return ret == Int32.MaxValue ? Count(torg) : ret;
                }
                public static int LowerBound(Node t, T v)
                {
                    var torg = t;
                    if (t == null) return -1;

                    var idx = Count(t) - Count(t.R) - 1;
                    var ret = Int32.MaxValue;
                    while (t != null)
                    {
                        var cmp = t.V.CompareTo(v);
                        if (cmp >= 0)
                        {
                            if (cmp == 0) ret = Math.Min(ret, idx);
                            t = t.L;
                            if (t == null) ret = Math.Min(ret, idx);
                            idx -= t == null ? 0 : (Count(t.R) + 1);
                        }
                        else if (cmp < 0)
                        {
                            t = t.R;
                            idx += (Count(t == null ? null : t.L) + 1);
                            if (t == null) return idx;
                        }
                    }
                    return ret == Int32.MaxValue ? Count(torg) : ret;
                }
                public static Node Insert(Node t, T v)
                {
                    var ub = LowerBound(t, v);
                    return InsertByIdx(t, ub, v);
                }
                static Node InsertByIdx(Node t, int k, T v)
                {
                    var s = Split(t, k);
                    return Merge(Merge(s.Item1, new Node(v)), s.Item2);
                }
                public static IEnumerable<T> Enumerate(Node t)
                {
                    var ret = new List<T>();
                    Enumerate(t, ret);
                    return ret;
                }
                static void Enumerate(Node t, List<T> ret)
                {
                    if (t == null) return;
                    Enumerate(t.L, ret);
                    ret.Add(t.V);
                    Enumerate(t.R, ret);
                }
            }
            public class Set<T> where T : IComparable
            {
                protected BST<T>.Node _root;
                public T this[int idx] { get { return ElementAt(idx); } }
                public int Count() { return BST<T>.Count(_root); }
                public virtual void Insert(T v)
                {
                    if (_root == null) _root = new BST<T>.Node(v);
                    else
                    {
                        if (BST<T>.Find(_root, v) != null) return;
                        _root = BST<T>.Insert(_root, v);
                    }
                }
                public void Clear() { _root = null; }
                public void Remove(T v) { _root = BST<T>.Remove(_root, v); }
                public bool Contains(T v) { return BST<T>.Contains(_root, v); }
                public T ElementAt(int k)
                {
                    var node = BST<T>.FindByIndex(_root, k);
                    if (node == null) throw new IndexOutOfRangeException();
                    return node.V;
                }
                public int Count(T v) { return BST<T>.UpperBound(_root, v) - BST<T>.LowerBound(_root, v); }
                public int LowerBound(T v) { return BST<T>.LowerBound(_root, v); }
                public int UpperBound(T v) { return BST<T>.UpperBound(_root, v); }
                public Tuple<int, int> EqualRange(T v)
                {
                    if (!Contains(v)) return new Tuple<int, int>(-1, -1);
                    return new Tuple<int, int>(BST<T>.LowerBound(_root, v), BST<T>.UpperBound(_root, v) - 1);
                }
                public List<T> ToList() { return new List<T>(BST<T>.Enumerate(_root)); }
            }
            public class MultiSet<T> : Set<T> where T : IComparable
            { public override void Insert(T v) { if (_root == null) { _root = new BST<T>.Node(v); } else { _root = BST<T>.Insert(_root, v); } } }
        }

        class Graph
        {
            public static HashSet<int> ConnectedComponent(Dictionary<int, HashSet<int>> adj, int idx)
            {
                HashSet<int> comp = new HashSet<int>();
                comp.Add(idx);
                List<int> target = new List<int>();
                target.Add(idx);
                while (target.Count > 0)
                {
                    List<int> next = new List<int>();
                    foreach (var p in target)
                    {
                        foreach (var f in adj[p])
                        {
                            if (!comp.Contains(f))
                            {
                                next.Add(f);
                                comp.Add(f);
                            }
                        }
                    }
                    target = next;
                }
                return comp;
            }
        }

        static string ReadStr()
        {
            return Console.ReadLine();
        }
        static string[] ReadStrN()
        {
            return Console.ReadLine().Split(' ');
        }
        static int ReadInt()
        {
            return Convert.ToInt32(Console.ReadLine());
        }
        static int[] ReadIntN()
        {
            return Console.ReadLine().Split(' ').Select(s => Convert.ToInt32(s)).ToArray();
        }
        static long ReadLong()
        {
            return Convert.ToInt64(Console.ReadLine());
        }
        static long[] ReadLongN()
        {
            return Console.ReadLine().Split(' ').Select(s => Convert.ToInt64(s)).ToArray();
        }
        static Tuple<string, string>[] ReadTupleStr(int n)
        {
            List<Tuple<string, string>> list = new List<Tuple<string, string>>();
            for (int i = 0; i < n; ++i)
            {
                var ab = ReadStrN();
                list.Add(new Tuple<string, string>(ab[0], ab[1]));
            }
            return list.ToArray();
        }
        static Tuple<long, long>[] ReadTupleLong(int n)
        {
            List<Tuple<long, long>> list = new List<Tuple<long, long>>();
            for (int i = 0; i < n; ++i)
            {
                var ab = ReadLongN();
                list.Add(new Tuple<long, long>(ab[0], ab[1]));
            }
            return list.ToArray();
        }
        static Tuple<double, double>[] ReadTupleDouble(int n)
        {
            List<Tuple<double, double>> list = new List<Tuple<double, double>>();
            for (int i = 0; i < n; ++i)
            {
                var ab = ReadLongN();
                list.Add(new Tuple<double, double>(ab[0], ab[1]));
            }
            return list.ToArray();
        }
        static Dictionary<int, HashSet<int>> ReadAdjacencyList(int N, int M)
        {
            Dictionary<int, HashSet<int>> dict = new Dictionary<int, HashSet<int>>();
            for (int i = 0; i <= N; ++i)
            {
                dict.Add(i, new HashSet<int>());
            }
            for (int i = 0; i < M; ++i)
            {
                var ab = ReadIntN();
                dict[ab[0]].Add(ab[1]);
                dict[ab[1]].Add(ab[0]);
            }
            return dict;
        }
    }
}