Problem:
Score : 300 points

Problem Statement

There is a staircase with N steps. Takahashi is now standing at the foot of the stairs, that is, on the 0-th step.
He can climb up one or two steps at a time.

However, the treads of the a_1-th, a_2-th, a_3-th, \ldots, a_M-th steps are broken, so it is dangerous to set foot on those steps.

How many are there to climb up to the top step, that is, the N-th step, without setting foot on the broken steps?
Find the count modulo 1\ 000\ 000\ 007.

Constraints

1 \leq N \leq 10^5

0 \leq M \leq N-1

1 \leq a_1 < a_2 < ... < a_M \leq N-1

Input

Input is given from Standard Input in the following format:

N M
a_1
a_2
.
.
.
a_M

Output

Print the number of ways to climb up the stairs under the condition, modulo 1\ 000\ 000\ 007.

Sample Input 1

6 1
3

Sample Output 1

4

There are four ways to climb up the stairs, as follows:

0 \to 1 \to 2 \to 4 \to 5 \to 6

0 \to 1 \to 2 \to 4 \to 6

0 \to 2 \to 4 \to 5 \to 6

0 \to 2 \to 4 \to 6

Sample Input 2

10 2
4
5

Sample Output 2

0

There may be no way to climb up the stairs without setting foot on the broken steps.

Sample Input 3

100 5
1
23
45
67
89

Sample Output 3

608200469

Be sure to print the count modulo 1\ 000\ 000\ 007.

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

using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace ContestTemplate
{
    #region interface class

    /// <summary>
    /// IO method interface
    /// </summary>
    public interface IInputOutput
    {
        /// <summary>
        /// read a single line from any stream
        /// </summary>
        /// <returns></returns>
        string ReadLine();

        /// <summary>
        /// write the data as a single line to any stream
        /// </summary>
        /// <param name="data"></param>
        void WriteLine(string data);
    }

    /// <summary>
    /// executable interface
    /// </summary>
    public interface IRunner
    {
        /// <summary>
        /// execute main process
        /// </summary>
        void Execute();
    }

    #endregion

    #region common class

    /// <summary>
    /// factory class of the main process runnger
    /// </summary>
    internal static class RunnerFactory
    {
        /// <summary>
        /// create executable main process runner
        /// </summary>
        /// <param name="isTest">test mode or one for submitting as a final code</param>
        /// <returns></returns>
        internal static IRunner Create(bool isTest)
        {
            if (isTest == false)
            {
                return new ConsoleInputOutputRunner();
            }
            else
            {
                return new TestRunner();
            }
        }
    }

    /// <summary>
    /// IO to/from console
    /// </summary>
    internal class ConsoleInputOutput : IInputOutput
    {
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        string IInputOutput.ReadLine()
        {
            return Console.ReadLine();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        void IInputOutput.WriteLine(string data)
        {
            Console.WriteLine(data);
        }
    }

    /// <summary>
    /// IO to/from test data
    /// </summary>
    internal class TestInputOutput : IInputOutput, IDisposable
    {
        /// <summary>
        /// 
        /// </summary>
        private readonly TextReader inputDataStream;

        /// <summary>
        /// 
        /// </summary>
        private readonly StringBuilder outputDataStream;

        /// <summary>
        /// 
        /// </summary>
        private bool isDisposed = false;

        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="input">test input data</param>
        internal TestInputOutput(string input)
        {
            this.inputDataStream = new StringReader(input);
            this.outputDataStream = new StringBuilder();
        }

        /// <summary>
        /// finalizer
        /// </summary>
        ~TestInputOutput()
        {
            this.Dispose(false);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            this.Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="isDisposing"></param>
        protected virtual void Dispose(bool isDisposing)
        {
            if (this.isDisposed == true)
            {
                return;
            }

            if (isDisposing == true)
            {
                this.inputDataStream.Dispose();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        string IInputOutput.ReadLine()
        {
            return this.inputDataStream.ReadLine();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="data"></param>
        void IInputOutput.WriteLine(string data)
        {
            this.outputDataStream.Append(data + "\n");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        internal string ObtainOutputData()
        {
            return this.outputDataStream.ToString();
        }
    }

    /// <summary>
    /// console input/output executable runner 
    /// for submitting as a final code
    /// </summary>
    internal class ConsoleInputOutputRunner : IRunner
    {
        /// <summary>
        /// execute main proces using console input/ ouput
        /// </summary>
        public void Execute()
        {
            Program.DoMainProcess(new ConsoleInputOutput());
        }
    }

    /// <summary>
    /// unit test executable runner
    /// </summary>
    internal class TestRunner : IRunner
    {
        /// <summary>
        /// execute all test cases
        /// </summary>
        public void Execute()
        {
            foreach (var inputAndExpectedResult in TestDataForLocal.ObtainTestInputAndExpectedResultMap())
            {
                var input = inputAndExpectedResult.Key;
                var expectedResult = inputAndExpectedResult.Value;

                Console.WriteLine(string.Format("TEST:: input=[\n{0}\n], \nexpectedOutput=[{1}]", input, expectedResult));

                using (var inputOutput = new TestInputOutput(input))
                {
                    Program.DoMainProcess(inputOutput);
                    var result = inputOutput.ObtainOutputData();

                    Console.WriteLine(string.Format("TEST:: result=[\n{0}], \njudge::[{1}]", result, result == expectedResult));
                    Console.WriteLine(string.Empty);
                }
            }

            // just to wait (to check the result)
            Console.ReadKey();
        }
    }

    #endregion

    #region test data

    /// <summary>
    /// unit test data
    /// </summary>
    internal static class TestDataForLocal
    {
        /// <summary>
        /// get the mapped data of input and expected result string
        /// **EDIT THIS DATA TO CHANGE TEST CASES** 
        /// </summary>
        /// <returns></returns>
        internal static Dictionary<string, string> ObtainTestInputAndExpectedResultMap()
        {
            return new Dictionary<string, string>()
            {
                {"1 0\n", "1\n"},
                {"2 0\n", "2\n"},
                {"15 0\n", "987\n"},
                {"6 1\n3", "4\n"},
                {"10 2\n4\n5", "0\n"},
                {"100 5\n1\n23\n45\n67\n89", "608200469\n"},
            };
        }
    }

    #endregion

    class Program
    {
        static void Main(string[] args)
        {
            const bool isTest = false;
            RunnerFactory.Create(isTest).Execute();
        }

        /// <summary>
        /// main algorithm of the question
        /// </summary>
        /// <param name="inputOuput"></param>
        internal static void DoMainProcess(IInputOutput inputOuput)
        {
            var line1 = inputOuput.ReadLine();
            var line1Array = line1.Split(' ');
            var n = int.Parse(line1Array[0]);
            var m = int.Parse(line1Array[1]);

            var mList = new List<int>();

            for (int i = 0; i < m ; i++)
            {
                var line2 = inputOuput.ReadLine();
                mList.Add(int.Parse(line2));

                if (i > 0)
                {
                    if (mList[i] == mList[i - 1] + 1)
                    {
                        inputOuput.WriteLine("0");
                        return;
                    }
                }
            }

            var cacheList = new long[n + 1];

            for (int i = 0; i < n + 1; i++)
            {
                cacheList[i] = -1;
            }

            long combination = calc(n, mList, cacheList) % 1000000007L;
            
            inputOuput.WriteLine(string.Format("{0}", combination));
            return;
        }

        internal static long calc(int n, List<int> mList, long[] cacheList)
        {
            if (n == 1)
            {
                cacheList[1] = 1;
                return cacheList[1];
            }

            if (n == 2)
            {
                if (mList.Any(x => x == n))
                {
                    cacheList[2] = 1;
                    return cacheList[2];
                }
                else
                {
                    cacheList[2] = 2;
                    return cacheList[2];
                }
            }

            if (mList.Any(x => x == n))
            {
                if (cacheList[n - 2] == -1)
                {
                    cacheList[n - 2] = calc(n - 2, mList, cacheList) / 2;
                }
     
                return cacheList[n - 2] % 1000000007L;
            }
            else
            {
                if (cacheList[n - 2] == -1)
                {
                    cacheList[n - 2] = calc(n - 2, mList, cacheList);
                }

                if (cacheList[n - 1] == -1)
                {
                    cacheList[n - 1] = calc(n - 1, mList, cacheList);
                }

                return (cacheList[n - 1] + cacheList[n - 2]) % 1000000007L;
            }
        }

    }

}