Problem:
Score : 600 points

Problem Statement

We have an integer sequence A of length N, where A_1 = X, A_{i+1} = A_i + D (1 \leq i < N ) holds.

Takahashi will take some (possibly all or none) of the elements in this sequence, and Aoki will take all of the others.

Let S and T be the sum of the numbers taken by Takahashi and Aoki, respectively. How many possible values of S - T are there?

Constraints

-10^8 \leq X, D \leq 10^8

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

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N X D

Output

Print the number of possible values of S - T.

Sample Input 1

3 4 2

Sample Output 1

8

A is (4, 6, 8).

There are eight ways for (Takahashi, Aoki) to take the elements: ((), (4, 6, 8)), ((4), (6, 8)), ((6), (4, 8)), ((8), (4, 6))), ((4, 6), (8))), ((4, 8), (6))), ((6, 8), (4))), and ((4, 6, 8), ()).

The values of S - T in these ways are -18, -10, -6, -2, 2, 6, 10, and 18, respectively, so there are eight possible values of S - T.

Sample Input 2

2 3 -3

Sample Output 2

2

A is (3, 0). There are two possible values of S - T: -3 and 3.

Sample Input 3

100 14 20

Sample Output 3

49805

Solution in C# (Mono 4.6.2.0) (judge verdict: Runtime Error)

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

public class Program
{
    private int N, X, D;

    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        X = sc.NextInt();
        D = sc.NextInt();

        if (D < 0)
        {
            X = -X;
            D = -D;
        }


        // Dで割ったあまり imos
        var map = new Dictionary<int, HashMap<long, int>>();

        for (int i = 0; i <= N; i++)
        {
            // 高橋君がi個取る

            // D部分は
            // Sum[0,i] から Sum[N-i,N-1]まで1刻みで構成可能

            long xx = X * i;

            int m = (int) (xx % D);
            if (m < 0)
            {
                m += D;
            }

            HashMap<long, int> o;
            if (!map.TryGetValue(m, out o))
            {
                map[m] = new HashMap<long, int>();
            }

            long min = xx + D * Sum(0, 1, i);
            long max = xx + D * Sum(N - i, 1, i);

            //Console.WriteLine($"{Sum(0, D, i)} {Sum(N - i, D, i)}");

            if (max < min)
            {
                long t = min;
                min = max;
                max = t;
            }

            map[m][(min - m) / D]++;
            map[m][(max - m + D) / D]--;

            //Console.WriteLine($"{m} {min} {(min - m) / D} {max} {(max - m + D) / D}");
        }

        long ans = 0;
        foreach (KeyValuePair<int, HashMap<long, int>> pair in map)
        {
            var array = pair.Value.ToArray();
            Array.Sort(array, (a, b) => a.Key.CompareTo(b.Key));
            int s = 0;
            long left = -1;
            bool f = false;
            foreach (KeyValuePair<long, int> valuePair in array)
            {
                s += valuePair.Value;
                if (s > 0 && !f)
                {
                    f = true;
                    left = valuePair.Key;
                }

                if (s == 0 && f)
                {
                    f = false;
                    ans += valuePair.Key - left;
                }
            }
        }

        Console.WriteLine(ans);
    }

    // 初項　公差　項数
    long Sum(long min, long d, int n)
    {
        return (min + min + d * (n - 1)) * n / 2;
    }

    public static void Main(string[] args)
    {
        new Program().Solve();
    }
}

class HashMap<K, V> : Dictionary<K, V>
{
    new public V this[K i]
    {
        get
        {
            V v;
            return TryGetValue(i, out v) ? v : base[i] = default(V);
        }
        set { base[i] = value; }
    }
}

class Scanner
{
    public Scanner()
    {
        _pos = 0;
        _line = new string[0];
    }

    const char Separator = ' ';
    private int _pos;
    private string[] _line;

    #region スペース区切りで取得

    public string Next()
    {
        if (_pos >= _line.Length)
        {
            _line = Console.ReadLine().Split(Separator);
            _pos = 0;
        }

        return _line[_pos++];
    }

    public int NextInt()
    {
        return int.Parse(Next());
    }

    public long NextLong()
    {
        return long.Parse(Next());
    }

    public double NextDouble()
    {
        return double.Parse(Next());
    }

    #endregion

    #region 型変換

    private int[] ToIntArray(string[] array)
    {
        var result = new int[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = int.Parse(array[i]);
        }

        return result;
    }

    private long[] ToLongArray(string[] array)
    {
        var result = new long[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = long.Parse(array[i]);
        }

        return result;
    }

    private double[] ToDoubleArray(string[] array)
    {
        var result = new double[array.Length];
        for (int i = 0; i < array.Length; i++)
        {
            result[i] = double.Parse(array[i]);
        }

        return result;
    }

    #endregion

    #region 配列取得

    public string[] Array()
    {
        if (_pos >= _line.Length)
            _line = Console.ReadLine().Split(Separator);

        _pos = _line.Length;
        return _line;
    }

    public int[] IntArray()
    {
        return ToIntArray(Array());
    }

    public long[] LongArray()
    {
        return ToLongArray(Array());
    }

    public double[] DoubleArray()
    {
        return ToDoubleArray(Array());
    }

    #endregion
}