Problem:
福縞軒

「福縞軒」は行列のできる人気のラーメン屋です。でも最近、お客さんの間から「待ち時間が長いのに、店に入ったら空席があるのは許せない」という声が聞こえるようになってきました。どうしてそんな不満が出るのか調べたいのですが、お店が開いているあいだは忙しくて、実際の行列の様子を調べることができません。しかし、長年の経験からお客さんが来る間隔や人数は分かっているので、それをもとに待ち時間の分析をすることにしました。

店内にはカウンターに向かって 17 の席があります。開店時間は正午で、お客さんは次のようにやってきます。

0 番から 99 番までの 100 組のグループが来ます。

i 番目のグループは正午から 5i 分後にお店に到着します。

i 番目のグループの人数は i % 5 が 1 のとき 5 人、それ以外のときは 2 人です。

(x % yは x を y で割ったときの余りを表わします。)

i 番目のグループは、席に着くと 17(i % 2) + 3(i % 3) + 19 分間で食事を済ませます。

最初の 10 グループの到着時刻、人数、食事時間は次のようになります。

グループ番号

0

1

2

3

4

5

6

7

8

9

到着時刻(分後)

0

5

10

15

20

25

30

35

40

45

人数(人)

2

5

2

2

2

2

5

2

2

2

食事時間(分)

19

39

25

36

22

42

19

39

25

36

また、お客さんを席に案内するときには、次のようにしています。

席には 0 から 16 までの番号が付いています。

x 人のグループは連続して x 個あいている席があった時だけ着席できます。

また、座れる場所が複数あった場合は、席の番号が最も小さくなるところに座ります。例えば、0、1、2、4、5番の席だけが空いていた場合、5 人のグループは着席できません。2 人のグループであれば 0、1 番に着席します。

一度着席したら、席を移動してもらうことはしません。

お客さんは 1 分単位で出入りします。各時刻には次の順序でお客さんを案内します。

前のグループの離席と同時に次のグループの着席が可能となります。

お客さんを着席させる際には、行列の先頭にいるグループから順に、できる限り多くのグループを同じ時刻に着席させます。行列の順序を追い越すことはしません。つまり、先頭のグループが着席できなければ、行列内の他のグループが着席できたとしても、着席させません。

その時刻に到着したグループは、行列が残っている場合は行列の最後尾に並びます。行列が無く、着席できる場合は着席し、できない場合は並んで待ちます。例として最初の 10 グループが到着するまでの様子を示すと以下のようになります。各行の3つの欄は、左から時刻、座席の様子、行列の様子を示しています。座席は「_」が空席で、番号はその席にその番号のグループが座っていることを示しています。

時刻: 座席 行列
0: 00_______________:
5: 0011111__________:
10: 001111122________:
15: 00111112233______:
18: 00111112233______:
19: __111112233______:
20: 44111112233______:
25: 4411111223355____:
30: 4411111223355____: 66666 グループ6が到着
34: 4411111223355____: 66666
35: 4411111__3355____: 6666677 グループ7が到着
40: 4411111__3355____: 666667788 グループ8が到着
41: 4411111__3355____: 666667788
42: __11111__3355____: 666667788
43: __11111__3355____: 666667788
44: 6666677883355____: グループ6、7、8が着席
45: 666667788335599__: グループ9が到着、着席

例えば、時刻 40 では 8 番目のグループが到着しますが、着席できないので行列に加わります。4 番目のグループは時刻 41 まで食事をします。時刻 42 では、4 番目のグループの席が空きますが、連続した席数が足りないので 6 番目のグループはまだ着席できません。1 番目のグループは時刻 43 まで食事をします。時刻 44 で 1 番目のグループの席が空くので、6 番目のグループが着席し、同時に 7 番目、8 番目のグループも着席します。9 番目のグループは時刻 45 で到着し、席が空いているのでそのまま着席します。

これらの情報を基にして、0 以上 99 以下の整数 n を入力として、n 番目グループのお客さんが待つ時間(分単位)を出力するプログラムを作成してください。

Input

複数のデータセットが与えられます。各データセットは１つの整数 n からなります。

データセットの数は 20 を超えません。

Output

各データセットについて、n 番目のお客の分単位の待ち時間(0 以上の整数)を１行に出力してください。

Sample Input

5
6
7
8

Output for the Sample Input

0
14
9
4

Solution in C# (judge verdict: Wrong Answer)

using System.Collections.Generic;
using System;

public class PriorityQueue<T> where T : IComparable
{
    private IComparer<T> _comparer = null;
    private int _type = 0;
    private T[] _heap;
    private int _sz = 0;
    private int _count = 0;
    /// <summary>
    /// Priority Queue with custom comparer
    /// </summary>
    public PriorityQueue(int maxSize, IComparer<T> comparer)
    {
        _heap = new T[maxSize];
        _comparer = comparer;
    }

    /// <summary>
    /// Priority queue
    /// </summary>
    /// <param name="maxSize">max size</param>
    /// <param name="type">0: asc, 1:desc</param>
    public PriorityQueue(int maxSize, int type = 0)
    {
        _heap = new T[maxSize];
        _type = type;
    }
    private int Compare(T x, T y)
    {
        if (_comparer != null) return _comparer.Compare(x, y);
        return _type == 0 ? x.CompareTo(y) : y.CompareTo(x);
    }
    public void Push(T x)
    {
        _count++;
        //node number
        var i = _sz++;
        while (i > 0)
        {
            //parent node number
            var p = (i - 1) / 2;

            if (Compare(_heap[p], x) <= 0) break;

            _heap[i] = _heap[p];
            i = p;
        }
        _heap[i] = x;
    }
    public T Pop()
    {
        _count--;
        T ret = _heap[0];
        T x = _heap[--_sz];

        int i = 0;
        while (i * 2 + 1 < _sz)
        {
            //children
            int a = i * 2 + 1;
            int b = i * 2 + 2;

            if (b < _sz && Compare(_heap[b], _heap[a]) < 0) a = b;

            if (Compare(_heap[a], x) >= 0) break;

            _heap[i] = _heap[a];
            i = a;
        }
        _heap[i] = x;
        return ret;
    }
    public int Count()
    {
        return _count;
    }
    public T Peek()
    {
        return _heap[0];
    }
    public bool Contains(T x)
    {
        for (int i = 0; i < _sz; i++) if (x.Equals(_heap[i])) return true;
        return false;
    }
    public void Clear()
    {
        while (this.Count() > 0) this.Pop();
    }
    public IEnumerator<T> GetEnumerator()
    {
        var ret = new List<T>();
        while (this.Count() > 0)
        {
            ret.Add(this.Pop());
        }
        foreach (var r in ret)
        {
            this.Push(r);
            yield return r;
        }
    }
    public T[] ToArray()
    {
        T[] array = new T[_sz];
        int i = 0;
        foreach (var r in this)
        {
            array[i++] = r;
        }
        return array;
    }
}
public class P2 : IComparable
{
    public int id { get; set; }
    public int dtime { get; set; }
    public int sid { get; set; }
    public int mem { get; set; }
    public int CompareTo(object obj)
    {
        var x = (P2)obj;
        if (this.dtime > x.dtime) return 1;
        else if (this.dtime == x.dtime) return 0;
        else return -1;
    }
}
public class P
{
    public int id { get; set; }
    public int atime { get; set; }
    public int mem { get; set; }
    public int mtime { get; set; }
}

public class Hello
{
    public static void Main()
    {
        string line;
        for (; (line = Console.ReadLine()) != null;)
        {
            var n = int.Parse(line.Trim());
            var q = new Queue<P>();
            for (int i = 0; i <= n; i++)
            {
                var w = 17 * (i % 2) + 3 * (i % 3) + 19;
                q.Enqueue(new P { id = i, atime = 5 * i, mtime = w, mem = i % 5 == 1 ? 5 : 2 });
            }
            var s = new bool[17];
            var pq = new PriorityQueue<P2>(100, 0);
            var now = 0;
            var wait = false;
            for (int i = 0; i <= 100; i++)
            {
                if (pq.Count() > 0)
                {
                    var te = pq.Peek();
                    var te2 = q.Peek();
                    if (te.dtime <= te2.atime | wait)
                    {
                        wait = false;
                        pq.Pop();
                        now = te.dtime;
                        reLSeat(s, te.sid, te.mem);
                    }
                    else
                    {
                        now = Math.Max(now, te2.atime);
                        if (putSeat(pq, s, te2, now, n))
                        {
                            if (n == te2.id) {  Console.WriteLine(now - te2.atime); goto next; }
                            q.Dequeue();
                        }
                        else wait = true;
                    }
                }
                else
                {
                    var te2 = q.Dequeue();
                    now = te2.atime;
                    putSeat(pq, s, te2, now, n);
                }
            }
            next:;
        }
    }
    public static bool putSeat(PriorityQueue<P2> pq, bool[] s, P te2, int now, int n)
    {
        var ws = checkSeat(s, te2.mem);
        if (ws == -1) return false;
        else
        {
            if (n == te2.id) {  return true; }
            pq.Push(new P2 { id = te2.id, dtime = now + te2.mtime, sid = ws, mem = te2.mem });
            return true;
        }
    }
    public static void reLSeat(bool[] s, int a, int b)
    {
        for (int i = a; i <= a + b - 1; i++) s[i] = false;
    }
    public static int checkSeat(bool[] s, int n)
    {
        if (n == 5)
        {
            for (int i = 0; i <= 12; i++)
                if (!s[i] && !s[i + 1] && !s[i + 2] && !s[i + 3] && !s[i + 4])
                {
                    s[i] = true; s[i + 1] = true; s[i + 2] = true; s[i + 3] = true; s[i + 4] = true;
                    return i;
                }
            return -1;
        }
        else
        {
            for (int i = 0; i <= 15; i++)
                if (!s[i] && !s[i + 1]) { s[i] = true; s[i + 1] = true; return i; }
            return -1;
        }
    }
}