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: Accepted)

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.NextLong();
        X = sc.NextLong();
        D = sc.NextLong();
        if (D < 0)
        {
            X = -X;
            D = -D;
        }

        if (D == 0)
        {
            if (X == 0)
            {
                // S = 0, T = 0
                Console.WriteLine(1);
                return;
            }
            else
            {
                Console.WriteLine(N + 1);
                return;
            }
        }

        // D > 0


        // 余り iで 
        var map = new Dictionary<long, Dictionary<long, long>>();
        map[0] = new Dictionary<long, long>();
        map[0][0] = 1;
        map[0][1] = -1;
        for (int i = 1; i <= N; i++)
        {
            // Sがi個取る

            // Aの小さいほう i個
            long min = (2 * X + (i - 1) * D) * i / 2;
            // Aの大きいほう i個 
            long max = (2 * X + (2 * N - i - 1) * D) * i / 2;

            // Console.WriteLine($"{i} {min} {max}");
            // D刻みで全部とれる
            long m = min % D;
            if (m < 0) m += D;

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

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

            long mnO;
            map[m].TryGetValue(mn, out mnO);
            map[m][mn] = mnO + 1;
            long mxO;
            map[m].TryGetValue(mx + 1, out mxO);
            map[m][mx + 1] = mxO - 1;
        }

        // imos

        long ans = 0;

        foreach (KeyValuePair<long, Dictionary<long, long>> keyValuePair in map)
        {
            var ar = keyValuePair.Value.ToArray();
            Array.Sort(ar, (a, b) => a.Key.CompareTo(b.Key));
            long left = -1;
            long sum = 0;
            bool f = false;
            foreach (KeyValuePair<long, long> pair in ar)
            {
                sum += pair.Value;
                if (f)
                {
                    if (sum == 0)
                    {
                        f = false;
                        var right = pair.Key;
                        // Console.WriteLine($"{keyValuePair.Key} {left} {right}");
                        ans += right - left;
                    }
                }
                else
                {
                    if (sum != 0)
                    {
                        f = true;
                        left = pair.Key;
                    }
                }
            }
        }

        Console.WriteLine(ans);
    }

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

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
}