Problem:
1年生 (A First Grader)

問題

JOI君は小学 1 年生である．JOI君は教わったばかりの足し算，引き算がとても好きで，数字が並んでいるのを見ると最後の 2 つの数字の間に「=」を入れ，残りの数字の間に必ず「+」または「-」を入れて等式を作って遊んでいる．例えば「8 3 2 4 8 7 2 4 0 8 8」から，等式「8+3-2-4+8-7-2-4-0+8=8」を作ることができる．

JOI 君は等式を作った後，それが正しい等式になっているかを計算して確かめる．ただし，JOI君はまだ負の数は知らないし，20 を超える数の計算はできない．したがって，正しい等式のうち左辺を左から計算したとき計算の途中で現れる数が全て 0 以上 20 以下の等式だけがJOI君が確かめられる正しい等式である．例えば，「8+3-2-4-8-7+2+4+0+8=8」は 正しい等式だが，途中に現れる 8+3-2-4-8 が負の数なのでJOI君はこの等式が正しいかどうか確かめることができない．

入力として数字の列が与えられたとき，JOI君が作り，確かめることができる正しい等式の個数を求めるプログラムを作成せよ．

入力

入力ファイルは 2 行からなる．1 行目には並んでいる数字の個数を表す整数 N （3 ≤ N ≤ 100）が書かれている．2 行目には 0 以上 9 以下の整数が N 個，空白を区切りとして書かれている．

与えられる入力データの 60% では，JOI君が作り，確かめることができる正しい等式の個数は 231-1 を超えない．また，与えられる入力データの全てにおいて，JOI君が作り，確かめることができる正しい等式の個数は 263-1 を超えない．

出力

JOI君が作り，確かめることができる正しい等式の個数を表す整数を 1 行で出力せよ．

入出力例

入力例 1

11
8 3 2 4 8 7 2 4 0 8 8

出力例 1

10

入力例 1 において，JOI君は 10 個の正しい等式

8+3-2-4+8-7-2-4-0+8=8
8+3-2-4+8-7-2-4+0+8=8
8+3+2+4-8-7+2-4-0+8=8
8+3+2+4-8-7+2-4+0+8=8
8+3-2-4+8-7+2+4-0-8=8
8+3-2-4+8-7+2+4+0-8=8
8-3+2+4-8+7+2+4-0-8=8
8-3+2+4-8+7+2+4+0-8=8
8-3+2-4+8+7+2-4-0-8=8
8-3+2-4+8+7+2-4+0-8=8

を作り，確かめることができるので 10 を出力する．

入力例 2

40
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1

出力例 2

7069052760

入力例 2 において，答えが 32 bit符号付き整数の範囲に収まらないことに注意せよ．

問題文と自動審判に使われるデータは、情報オリンピック日本委員会が作成し公開している問題文と採点用テストデータです。

Solution in C# (judge verdict: Accepted)

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

class Solver
{
    void Solve()
    {
        var n = sc.Integer();
        var a = sc.IntArray(n);
        var dp = new long[n, 25];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < 25; j++)
                dp[i, j] = -1;
        Func<int,int, long> dfs = null;
        dfs = (pos,value) =>
            {
                if (pos == n - 1)
                {
                    if (value == a[n - 1])
                        return 1;
                    else return 0;
                }
                if (dp[pos,value] >= 0)
                    return dp[pos,value];
                var p = value + a[pos];
                var m=value-a[pos];
                long count=0;
                if (p >= 0 && p <= 20)
                    count += dfs(pos + 1, p);
                if (m >= 0 && m <= 20)
                    count += dfs(pos + 1, m);
                return dp[pos,value] = count;

            };
        Printer.PrintLine(dfs(1,a[0]));
        
    }
    static void Main()
    {
#if DEBUG
        var oStream = new System.IO.FileStream("debug.txt", System.IO.FileMode.Create, System.IO.FileAccess.Write);
        var iStream = new System.IO.FileStream("input.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
        Console.SetIn(new System.IO.StreamReader(iStream));
        System.Diagnostics.Debug.AutoFlush = true;
        System.Diagnostics.Debug.Listeners.Add(new System.Diagnostics.TextWriterTraceListener(new System.IO.StreamWriter(oStream, System.Text.Encoding.UTF8)));
        try
        {
#endif
            var solver = new Solver();
            solver.Solve();
#if DEBUG
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine(ex.StackTrace);
        }
        Console.ReadKey(true);
#endif
    }
    _Scanner sc = new _Scanner(Console.In);

}
static public class Printer
{
    static readonly private System.IO.TextWriter writer;
    static readonly private System.Globalization.CultureInfo info;
    static string Separator { get; set; }
    static Printer()
    {
        writer = Console.Out;
        info = System.Globalization.CultureInfo.InvariantCulture;
        Separator = " ";
    }

    static public void Print(int num) { writer.Write(num.ToString(info)); }
    static public void Print(int num, string format) { writer.Write(num.ToString(format, info)); }
    static public void Print(long num) { writer.Write(num.ToString(info)); }
    static public void Print(long num, string format) { writer.Write(num.ToString(format, info)); }
    static public void Print(double num) { writer.Write(num.ToString(info)); }
    static public void Print(double num, string format) { writer.Write(num.ToString(format, info)); }
    static public void Print(string str) { writer.Write(str); }
    static public void Print(string format, params object[] arg) { writer.Write(format, arg); }
    static public void Print(IEnumerable<char> sources) { writer.Write(sources.AsString()); }
    static public void Print(params object[] arg)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in arg)
        {
            res.AppendFormat(info, "{0}", x);
            if (!string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.Write(res.ToString(0, res.Length - Separator.Length));
    }
    static public void Print<T>(IEnumerable<T> sources)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in sources)
        {
            res.AppendFormat(info, "{0}", x);
            if (string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.Write(res.ToString(0, res.Length - Separator.Length));
    }
    static public void PrintLine(int num) { writer.WriteLine(num.ToString(info)); }
    static public void PrintLine(int num, string format) { writer.WriteLine(num.ToString(format, info)); }
    static public void PrintLine(long num) { writer.WriteLine(num.ToString(info)); }
    static public void PrintLine(long num, string format) { writer.WriteLine(num.ToString(format, info)); }
    static public void PrintLine(double num) { writer.WriteLine(num.ToString(info)); }
    static public void PrintLine(double num, string format) { writer.WriteLine(num.ToString(format, info)); }
    static public void PrintLine(string str) { writer.WriteLine(str); }
    static public void PrintLine(string format, params object[] arg) { writer.WriteLine(format, arg); }
    static public void PrintLine(IEnumerable<char> sources) { writer.WriteLine(sources.AsString()); }
    static public void PrintLine(params object[] arg)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in arg)
        {
            res.AppendFormat(info, "{0}", x);
            if (!string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.WriteLine(res.ToString(0, res.Length - Separator.Length));
    }
    static public void PrintLine<T>(IEnumerable<T> sources)
    {
        var res = new System.Text.StringBuilder();
        foreach (var x in sources)
        {
            res.AppendFormat(info, "{0}", x);
            if (!string.IsNullOrEmpty(Separator))
                res.Append(Separator);
        }
        writer.WriteLine(res.ToString(0, res.Length - Separator.Length));
    }
}
public class _Scanner
{
    readonly private System.Globalization.CultureInfo info;
    readonly System.IO.TextReader reader;
    string[] buffer = new string[0];
    int position;

    public char[] Separator { get; set; }
    public _Scanner(System.IO.TextReader reader, string separator = null, System.Globalization.CultureInfo info = null)
    {
        if (reader == null)
            throw new ArgumentNullException("reader");
        this.reader = reader;
        if (string.IsNullOrEmpty(separator))
            separator = " ";
        this.Separator = separator.ToCharArray();
        this.info = info ?? System.Globalization.CultureInfo.InvariantCulture;
    }
    public string Scan()
    {
        if (this.position < this.buffer.Length)
            return this.buffer[this.position++];
        this.buffer = this.reader.ReadLine().Split(this.Separator, StringSplitOptions.RemoveEmptyEntries);
        this.position = 0;
        return this.buffer[this.position++];
    }

    public string[] ScanToEndLine()
    {
        if (this.position >= this.buffer.Length)
            return this.reader.ReadLine().Split(this.Separator, StringSplitOptions.RemoveEmptyEntries);
        var size = this.buffer.Length - this.position;
        var ar = new string[size];
        Array.Copy(this.buffer, position, ar, 0, size);
        return ar;

    }

    public string ScanLine()
    {
        if (this.position >= this.buffer.Length)
            return this.reader.ReadLine();
        else
        {
            var sb = new System.Text.StringBuilder();
            for (; this.position < buffer.Length; this.position++)
            {
                sb.Append(this.buffer[this.position]);
                sb.Append(' ');
            }
            return sb.ToString();
        }
    }
    public string[] ScanArray(int length)
    {
        var ar = new string[length];
        for (int i = 0; i < length; i++)
        {
            ar[i] = this.Scan();
        }
        return ar;
    }

    public int Integer()
    {
        return int.Parse(this.Scan(), info);
    }
    public long Long()
    {
        return long.Parse(this.Scan(), info);
    }
    public double Double()
    {
        return double.Parse(this.Scan(), info);
    }
    public double Double(string str)
    {
        return double.Parse(str, info);
    }

    public int[] IntArray(int length)
    {
        var a = new int[length];
        for (int i = 0; i < length; i++)
            a[i] = this.Integer();
        return a;
    }
    public long[] LongArray(int length)
    {
        var a = new long[length];
        for (int i = 0; i < length; i++)
            a[i] = this.Long();
        return a;
    }
    public double[] DoubleArray(int length)
    {
        var a = new double[length];
        for (int i = 0; i < length; i++)
            a[i] = this.Double();
        return a;
    }

}
static public partial class EnumerableEx
{
    static public string AsString(this IEnumerable<char> source)
    {
        return new string(source.ToArray());
    }
    static public T[] EnumerateArray<T>(this int count, Func<int, T> selector)
    {
        var ret = new T[count];
        for (int i = 0; i < count; i++)
            ret[i] = selector(i);
        return ret;
    }
}

//*/