Problem:
Score : 300 points

Problem Statement

Takahashi, who lives on the number line, is now at coordinate X. He will make exactly K moves of distance D in the positive or negative direction.

More specifically, in one move, he can go from coordinate x to x + D or x - D.

He wants to make K moves so that the absolute value of the coordinate of the destination will be the smallest possible.

Find the minimum possible absolute value of the coordinate of the destination.

Constraints

-10^{15} \leq X \leq 10^{15}

1 \leq K \leq 10^{15}

1 \leq D \leq 10^{15}

All values in input are integers.

Input

Input is given from Standard Input in the following format:

X K D

Output

Print the minimum possible absolute value of the coordinate of the destination.

Sample Input 1

6 2 4

Sample Output 1

2

Takahashi is now at coordinate 6. It is optimal to make the following moves:

Move from coordinate 6 to (6 - 4 =) 2.

Move from coordinate 2 to (2 - 4 =) -2.

Here, the absolute value of the coordinate of the destination is 2, and we cannot make it smaller.

Sample Input 2

7 4 3

Sample Output 2

1

Takahashi is now at coordinate 7. It is optimal to make, for example, the following moves:

Move from coordinate 7 to 4.

Move from coordinate 4 to 7.

Move from coordinate 7 to 4.

Move from coordinate 4 to 1.

Here, the absolute value of the coordinate of the destination is 1, and we cannot make it smaller.

Sample Input 3

10 1 2

Sample Output 3

8

Sample Input 4

1000000000000000 1000000000000000 1000000000000000

Sample Output 4

1000000000000000

The answer can be enormous.

Solution in C# (Mono-csc 3.5.0) (judge verdict: Accepted)

namespace AtCoder
{
    using System;
    using System.Linq;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Text.RegularExpressions;

    class Program
    {
        static void Main()
        {
            var input = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();
            var x = input[0];
            var k = input[1];
            var d = input[2];
            long? guusuu = null;
            long? kisuu = null;

            long shou = Math.Abs(x) / d;
            long amari = Math.Abs(x) % d;
            long kaisuu = k - shou;
            if (shou > k)
            {
                var ans = Math.Abs(x) - (k * d);
                Output(ans.ToString());
                return;
            }
            //あまり0かつ残り回数が偶数なら０
            else if (amari == 0 && kaisuu % 2 == 0)
            {
                Output(0.ToString());
                return;
            }
            //あまり0かつ残り回数が奇数ならd
            else if (amari == 0 && kaisuu % 2 == 1)
            {
                Output(d.ToString());
                return;
            }
            else
            {
                x = amari;
                for (int i = 0; i < k - shou; i++)
                {

                    x = Math.Abs(Math.Abs(x) - d);

                    if (x > d)
                    {
                        continue;
                    }
                    if (i % 2 == 0)
                    {
                        guusuu = x;
                    }
                    else
                    {
                        kisuu = x;
                    }
                    if (guusuu != null && kisuu != null)
                    {
                        if (kaisuu % 2 == 0)
                        {
                            Output(kisuu.ToString());
                            return;
                        }
                        else
                        {
                            Output(guusuu.ToString());
                            return;
                        }
                    }
                }
            }
            Output(x.ToString());
        }
        private static void Output(string str)
        {
            var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
            Console.SetOut(sw);

            Console.WriteLine(str);

            Console.Out.Flush();
        }
    }
    static class Extentions
    {
        #region 拡張メソッド（string）

        public static string LeftB(this string stTarget, int iByteSize)
        {
            return MidB(stTarget, 1, iByteSize);
        }

        public static string MidB(this string stTarget, int iStart)
        {
            System.Text.Encoding hEncoding = System.Text.Encoding.GetEncoding("utf-8");
            byte[] bBytes = hEncoding.GetBytes(stTarget);

            return hEncoding.GetString(bBytes, iStart - 1, bBytes.Length - iStart + 1);
        }

        public static string MidB(this string stTarget, int iStart, int iByteSize)
        {
            System.Text.Encoding hEncoding = System.Text.Encoding.GetEncoding("utf-8");
            byte[] bBytes = hEncoding.GetBytes(stTarget);

            return hEncoding.GetString(bBytes, iStart - 1, iByteSize);
        }

        public static string RightB(this string stTarget, int iByteSize)
        {
            System.Text.Encoding hEncoding = System.Text.Encoding.GetEncoding("utf-8");
            byte[] bBytes = hEncoding.GetBytes(stTarget);

            return hEncoding.GetString(bBytes, bBytes.Length - iByteSize, iByteSize);
        }

        public static bool IsNullOrEmpty(this string str)
        {
            return string.IsNullOrEmpty(str);
        }

        /// <summary>
        /// カルチャに依存した比較、または大文字と小文字を区別しない比較などの序数による比較を指定できる Contains。
        /// </summary>
        /// <param name="value">対象文字列</param>
        /// <param name="partialValue">部分文字列</param>
        /// <param name="comparison">カルチャ、大文字と小文字の区別、および並べ替え規則を指定する StringComparison</param>
        /// <returns>一致する場合に true を返します。</returns>
        public static bool Contains(this string value, string partialValue, StringComparison comparison = 0)
        {
            return value.IndexOf(partialValue, comparison) >= 0;
        }

        public static bool IsNumeric(this string value)
        {
            return decimal.TryParse(value, out decimal d);
        }
        public static int ToInt32(this String number, int retValue = 0)
        {
            if (!number.IsNumeric()) return retValue;
            return int.Parse(number);
        }

        #endregion
    }
}
/*
 
        static void Main()
        {
            var input = System.Console.ReadLine().ToArray();
            var a = input[0];
            var b = input[1];
            var c = input[2];
            var rain = 0;
            if (a == 'R') rain++;
            if (b == 'R') rain++;
            if (c == 'R') rain++;
            if (rain > 0 && b != 'R') rain--;

            Output(rain.ToString());
        }
*/
/*
    using System;
    using System.Collections.Generic;
    using System.Linq;

    // 整数の入力========================================
    string[] input = Console.ReadLine().Split(' ');
    int a = int.Parse(input[0]);
    int b = int.Parse(input[1]);
    int c = int.Parse(Console.ReadLine());
    
    //配列操作========================================
    var a = System.Console.ReadLine().Split(' ').Select((x) => long.Parse(x)).ToArray();

    int[] a = new int[n];
    for (int i = 0; i < n; i++)
    {
        a[i] = int.Parse(input2[i]);
    }
    
    Array.Sort(a);
    Array.Reverse(a);
    
    // 最小公倍数========================================
    public static decimal Lcm(decimal a, decimal b)
    {
        return a * b / Gcd(a, b);
    }

    // ユークリッドの互除法 ========================================
    public static decimal Gcd(decimal a, decimal b)
    {
        if (a < b)
        {
            // 引数を入替えて自分を呼び出す
            return Gcd(b, a);
        }
        while (b != 0)
        {
            var remainder = a % b;
            a = b;
            b = remainder;
        }
        return a;
    }

    //出力========================================
    Console.WriteLine("");


    var sb = new StringBuilder();
    for (int j = 0; j<n; j++)
    {
        sb.AppendLine(a[j].ToString());
    }
    var sw = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false };
    Console.SetOut(sw);
    Console.WriteLine(sb.ToString());
    Console.Out.Flush();
*/