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: Wrong Answer)

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

public class Program
{
    private long 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;
        }

        if (D == 0)
        {
            Console.WriteLine(N + 1);
            return;
        }

        var map = new Dictionary<long, HashMap<long, long>>();

        for (int i = 0; i <= N; i++)
        {
            // 高橋君がi個取る
            if (i == 0)
            {
                map[0] = new HashMap<long, long>();
                map[0][0]++;
                map[0][1]--;
                continue;
            }

            // 0 ~ i-1の和
            long min = (i - 1) * i / 2;

            // N-i ~ N-1
            long max = (N - i + N - 1) * i / 2;

            long xx = X * i;

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

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

            long mn = (xx - m) / D + min;
            long mx = (xx - m) / D + max;

            map[m][mn]++;
            map[m][mx + 1]--;
        }

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

        Console.WriteLine(ans);
    }


    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
}