using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using SB = System.Text.StringBuilder;
//using System.Threading.Tasks;
//using System.Text.RegularExpressions;
//using System.Globalization;
//using System.Diagnostics;
using static System.Console;
using System.Numerics;
using static System.Math;
using pair = Pair<int, int>;

class Program
{
    static void Main()
    {
        //SetOut(new StreamWriter(OpenStandardOutput()) { AutoFlush = false });
        new Program().solve();
        Out.Flush();
    }
    readonly Scanner cin = new Scanner();
    readonly int[] dd = { 0, 1, 0, -1, 0 }; //→↓←↑
    readonly int mod = 1000000007;
    readonly int dom = 998244353;
    bool chmax<T>(ref T a, T b) where T : IComparable<T> { if (a.CompareTo(b) < 0) { a = b; return true; } return false; }
    bool chmin<T>(ref T a, T b) where T : IComparable<T> { if (b.CompareTo(a) < 0) { a = b; return true; } return false; }

    bool calc(int day, int[] K, List<int>[] L, int Sum)
    {
        int used = 0;
        int money = day;
        for (int i = day - 1; i >= 0; i--)
        {
            if (i < L.Length)
            {
                foreach (var v in L[i])
                {
                    int buy = Min(K[v], money);
                    money -= buy;
                    K[v] -= buy;
                    used += buy;
                }
            }
            money = Min(i, money);
        }

        int remain = Sum - used;

        return remain * 2 <= (day - used);

    }
    void solve()
    {
        int N = cin.nextint;
        int M = cin.nextint;
        var K = cin.scanint;

        var L = new List<int>[N];
        for (int i = 0; i < L.Length; i++)
        {
            L[i] = new List<int>();
        }
        for (int i = 0; i < M; i++)
        {
            L[cin.nextint - 1].Add(cin.nextint - 1);
        }
        int Sum = K.Sum();

        int ng = 0;
        int ok = Sum * 2;
        while (ok - ng > 1)
        {
            int mid = (ok + ng) / 2;

            var Z = new int[N];
            for (int i = 0; i < Z.Length; i++)
            {
                Z[i] = K[i];
            }

            if (calc(mid, Z, L, Sum))
            {
                ok = mid;
            }
            else
            {
                ng = mid;
            }
        }

        WriteLine(ok);

    }

}

static class Ex
{
    public static void join<T>(this IEnumerable<T> values, string sep = " ") => WriteLine(string.Join(sep, values));
    public static string concat<T>(this IEnumerable<T> values) => string.Concat(values);
    public static string reverse(this string s) { var t = s.ToCharArray(); Array.Reverse(t); return t.concat(); }

    public static int lower_bound<T>(this IList<T> arr, T val) where T : IComparable<T>
    {
        int low = 0, high = arr.Count;
        int mid;
        while (low < high)
        {
            mid = ((high - low) >> 1) + low;
            if (arr[mid].CompareTo(val) < 0) low = mid + 1;
            else high = mid;
        }
        return low;
    }
    public static int upper_bound<T>(this IList<T> arr, T val) where T : IComparable<T>
    {
        int low = 0, high = arr.Count;
        int mid;
        while (low < high)
        {
            mid = ((high - low) >> 1) + low;
            if (arr[mid].CompareTo(val) <= 0) low = mid + 1;
            else high = mid;
        }
        return low;
    }
}

class Pair<T, U> : IComparable<Pair<T, U>> where T : IComparable<T> where U : IComparable<U>
{
    public T f; public U s;
    public Pair(T f, U s) { this.f = f; this.s = s; }
    public int CompareTo(Pair<T, U> a) => f.CompareTo(a.f) != 0 ? f.CompareTo(a.f) : s.CompareTo(a.s);
    public override string ToString() => $"{f} {s}";
}

class Scanner
{
    string[] s; int i;
    readonly char[] cs = new char[] { ' ' };
    public Scanner() { s = new string[0]; i = 0; }
    public string[] scan => ReadLine().Split();
    public int[] scanint => Array.ConvertAll(scan, int.Parse);
    public long[] scanlong => Array.ConvertAll(scan, long.Parse);
    public double[] scandouble => Array.ConvertAll(scan, double.Parse);
    public string next
    {
        get
        {
            if (i < s.Length) return s[i++];
            string st = ReadLine();
            while (st == "") st = ReadLine();
            s = st.Split(cs, StringSplitOptions.RemoveEmptyEntries);
            i = 0;
            return next;
        }
    }
    public int nextint => int.Parse(next);
    public long nextlong => long.Parse(next);
    public double nextdouble => double.Parse(next);
}


using System;
using System.Linq;
using CompLib.Util;

public class Program
{
    int N, M;
    int[] K;
    int[] D, T;
    int[] index;
    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        M = sc.NextInt();
        K = sc.IntArray();
        D = new int[M];
        T = new int[M];
        for (int i = 0; i < M; i++)
        {
            D[i] = sc.NextInt();
            T[i] = sc.NextInt() - 1;
        }
        index = new int[M];
        for (int i = 0; i < M; i++)
        {
            index[i] = i;
        }

        Array.Sort(index, (l, r) => D[l].CompareTo(D[r]));

        // n種類ある
        // 毎日1獲得
        // 通常2 セール中は1支払えば買える
        // 種類iを丁度k[i]個買う
        // 毎日0個以上注文できる
        // 種類t[j]はd[j]日にセール

        //
        int ng = -1;
        int ok = 400000;
        while (ok - ng > 1)
        {
            int mid = (ok + ng) / 2;
            if (C(mid)) ok = mid;
            else ng = mid;
        }

        Console.WriteLine(ok);
    }

    // day日に達成できるか?
    bool C(int day)
    {
        // 区間内セール
        // 種類ごと一番最後
        // 前から

        int[] s = new int[N];
        for (int i = 0; i < N; i++)
        {
            s[i] = int.MaxValue;
        }

        for (int i = 0; i < M; i++)
        {
            if (D[index[i]] <= day)
            {
                s[T[index[i]]] = D[index[i]];
            }
        }

        var tmp = new int[N];
        for (int i = 0; i < N; i++)
        {
            tmp[i] = i;
        }
        Array.Sort(tmp, (l, r) => s[l].CompareTo(s[r]));
        //if (day == 8)
        //{
        //    Console.WriteLine("-----");
        //    Console.WriteLine(day);
        //    Console.WriteLine(string.Join(" ", s));
        //    Console.WriteLine(string.Join(" ", tmp));
        //}
        int nokori = 0;
        int m = 0;
        int p = 0;
        for (int i = 0; i < N; i++)
        {
            if (s[tmp[i]] == int.MaxValue)
            {
                nokori += K[tmp[i]];
            }
            else
            {
                // 買える分
                // s[i] - m

                int tt = Math.Min(K[tmp[i]], s[tmp[i]] - m);
                p += tt;
                m += tt;
                nokori += K[tmp[i]] - tt;
                //if (day == 8)
                //{
                //    Console.WriteLine($"{tmp[i]} {tt} {m}");
                //}
            }
        }
        //if(day == 8)
        //{
        //    Console.WriteLine("aaaa" + m);
        //}
        return nokori * 2 <= day - m;
    }

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

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

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

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

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            _line = Console.ReadLine().Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


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

namespace CodeForces
{
    class Program
    {
        static int[] Power10 = new int[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };

        static void Main(string[] args)
        {
            string[] inputStr = Console.ReadLine().Split(' ');
            int m = Convert.ToInt32(inputStr[0]);
            int n = Convert.ToInt32(inputStr[1]);
            Console.WriteLine(FindNext(m, n));
        }

        static int FindNext(int m, int n)
        {
            int[] code = CalCode(m, n);
            int max = code.Max();
            int length = CalLength(code, max);
            int index = m + length;

            while (true)
            {
                index = NextIndex(max, index);
                int[] nCode = CalCode(index - length, n);

                if (code.Length == nCode.Length)
                {
                    bool flag = false;

                    for (int i = 0; i < code.Length; i++)
                    {
                        if (code[i] != nCode[i])
                        {
                            flag = true;
                            break;
                        }
                    }

                    if (!flag)
                        return index - length;
                }
            }
        }

        static int NextIndex(int code, int index)
        {
            int bCode = (code / 2);
            index /= Power10[bCode];
            int nCode = code;

            while (true)
            {
                index++;
                int nIndex = index;

                while (nIndex % 10 == 0)
                    nIndex /= 10;

                int mod = nIndex % 10;

                if (mod == 4 || mod == 7)
                    nCode++;
                else if (mod == 5 || mod == 8)
                    nCode--;

                if (nCode == code)
                    return index * Power10[code / 2];
            }
        }

        static int CalLength(int[] code, int max)
        {
            int length = 0;

            for (int i = 0; i < code.Length; i++)
            {
                if(code[i] == max)
                    break;

                length += Power10[code[i] / 2];
            }

            return length;
        }

        static int[] CalCode(int m, int n)
        {
            List<int> result = new List<int>();

            int add = 1, codeBase = 0;

            while (n != 0)
            {
                if (n < add)
                {
                    add /= 10;
                    codeBase -= 2;
                }
                else if (m % (add * 10) == 0 && add * 10 <= n)
                {
                    add *= 10;
                    codeBase += 2;
                }
                else
                {
                    int code = m / add;
                    if (code % 10 == 4 || code % 10 == 7)
                        result.Add(codeBase + 1);
                    else
                        result.Add(codeBase);

                    m += add;
                    n -= add;
                }
            }

            return result.ToArray();
        }
    }
}


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

namespace CodeForces
{
    class Program
    {
        static long[] Power10 = new long[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000 };

        static void Main(string[] args)
        {
            string[] inputStr = Console.ReadLine().Split(' ');
            int m = Convert.ToInt32(inputStr[0]);
            int n = Convert.ToInt32(inputStr[1]);
            Console.WriteLine(FindNext(m, n));
        }

        static int FindNext(int m, int n)
        {
            int[] code = CalCode(m, n);
            int max = code.Max();
            int length = CalLength(code, max);
            int index = m + length;

            while (true)
            {
                index = NextIndex(max, index);
                int[] nCode = CalCode(index - length, n);

                if (code.Length == nCode.Length)
                {
                    bool flag = false;

                    for (int i = 0; i < code.Length; i++)
                    {
                        if (code[i] != nCode[i])
                        {
                            flag = true;
                            break;
                        }
                    }

                    if (!flag)
                        return index - length;
                }
            }
        }

        static int NextIndex(int code, int index)
        {
            int bCode = code / 10;
            index /= (int)Power10[bCode];
            int nCode = code;
            int dIndex = 0;

            while (index % 10 == 7)
            {
                dIndex++;
                index /= 10;
            }

            if (index % 10 == 4)
                index += 3;
            else if (index % 10 == 6 || index % 10 == 3)
                index += 2;
            else
            {
                index++;
                int add = 0;

                while (index % Power10[add + 1] == 0 && index >= Power10[add + 1])
                    add++;

                int nIndex = index / (int)Power10[add];

                if (nIndex % 10 == 4 || nIndex % 10 == 7)
                    index += (int)Power10[add];
            }

            for (int i = 0; i < dIndex; i++)
                index = index * 10 + 4;

            return index * (int)Power10[bCode];
        }

        static int CalLength(int[] code, int max)
        {
            int length = 0;

            for (int i = 0; i < code.Length; i++)
            {
                if(code[i] == max)
                    break;

                length += (int)Power10[code[i] / 10];
            }

            return length;
        }

        static int[] CalCode(int m, int n)
        {
            List<int> result = new List<int>();
            int add = 0, codeBase = 0, t = m - 1;

            while (t > 0)
            {
                if (t % 10 == 4 || t % 10 == 7)
                    codeBase++;

                t /= 10;
            }

            while (n != 0)
            {
                if (n < Power10[add])
                {
                    add--;
                    codeBase -= 10;
                }
                else if (m % Power10[add + 1] == 0 && Power10[add + 1] <= n)
                {
                    add++;
                    codeBase += 10;
                }
                else
                {
                    int nIndex = m;

                    while (nIndex % 10 == 0 && nIndex > 0)
                        nIndex /= 10;

                    int mod = nIndex % 10;

                    if (mod == 4 || mod == 7)
                        codeBase++;
                    else if (mod == 5 || mod == 8)
                        codeBase--;

                    result.Add(codeBase);
                    m += (int)Power10[add];
                    n -= (int)Power10[add];
                }
            }

            return result.ToArray();
        }
    }
}


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

namespace CodeForces
{
    class Program
    {
        static long[] Power10 = new long[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000 };

        static void Main(string[] args)
        {
            string[] inputStr = Console.ReadLine().Split(' ');
            int m = Convert.ToInt32(inputStr[0]);
            int n = Convert.ToInt32(inputStr[1]);
            Console.WriteLine(FindNext(m, n));
        }

        static int FindNext(int m, int n)
        {
            int[] code = CalCode(m, n);
            int max = code.Max();
            int length = CalLength(code, max);
            int index = m + length;

            while (true)
            {
                index = NextIndex(max, index);
                int[] nCode = CalCode(index - length, n);

                if (code.Length == nCode.Length)
                {
                    bool flag = false;

                    for (int i = 0; i < code.Length; i++)
                    {
                        if (code[i] != nCode[i])
                        {
                            flag = true;
                            break;
                        }
                    }

                    if (!flag)
                        return index - length;
                }
            }
        }

        static int NextIndex(int code, int index)
        {
            int bCode = code / 10;
            index /= (int)Power10[bCode];
            int nCode = code;
            int dIndex = 0;

            while (index % 10 == 7)
            {
                dIndex++;
                index /= 10;
            }

            if (index % 10 == 4)
                index += 3;
            else if (index % 10 == 6 || index % 10 == 3)
                index += 2;
            else
            {
                index++;
                int add = 0;

                while (index % Power10[add + 1] == 0)
                    add++;

                int nIndex = index / (int)Power10[add];

                if (nIndex % 10 == 4 || nIndex % 10 == 7)
                    index += (int)Power10[add];
            }

            for (int i = 0; i < dIndex; i++)
                index = index * 10 + 4;

            return index * (int)Power10[bCode];
        }

        static int CalLength(int[] code, int max)
        {
            int length = 0;

            for (int i = 0; i < code.Length; i++)
            {
                if(code[i] == max)
                    break;

                length += (int)Power10[code[i] / 10];
            }

            return length;
        }

        static int[] CalCode(int m, int n)
        {
            List<int> result = new List<int>();
            int add = 0, codeBase = 0, t = m - 1;

            while (t > 0)
            {
                if (t % 10 == 4 || t % 10 == 7)
                    codeBase++;

                t /= 10;
            }

            while (n != 0)
            {
                if (n < Power10[add])
                {
                    add--;
                    codeBase -= 10;
                }
                else if (m % Power10[add + 1] == 0 && Power10[add + 1] <= n)
                {
                    add++;
                    codeBase += 10;
                }
                else
                {
                    int nIndex = m;

                    while (nIndex % 10 == 0)
                        nIndex /= 10;

                    int mod = nIndex % 10;

                    if (mod == 4 || mod == 7)
                        codeBase++;
                    else if (mod == 5 || mod == 8)
                        codeBase--;

                    result.Add(codeBase);
                    m += (int)Power10[add];
                    n -= (int)Power10[add];
                }
            }

            return result.ToArray();
        }
    }
}


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

namespace CodeForces
{
    class Program
    {
        static long[] Power10 = new long[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000, 100000000000 };

        static void Main(string[] args)
        {
            long k = GetNext(5000037, 1);
            string[] inputStr = Console.ReadLine().Split(' ');
            int m = Convert.ToInt32(inputStr[0]);
            int n = Convert.ToInt32(inputStr[1]);
            Console.WriteLine(FindNext(m, n));
        }

        static int FindNext(int m, int n)
        {
            int[] code = CalCode(m, n);
            int max = code.Max();
            int min = code.Min();
            int maxLength = CalLength(code, max);
            int minLength = CalLength(code, min);
            long index = m + maxLength;
            long index2 = m + minLength;
            int pMin = (int)Power10[min / 10];
            int pMax = (int)Power10[max / 10];

            while (true)
            {
                index2 = GetNext(index2 / pMin, min % 10) * pMin;
                index = GetNext(index / pMax, max % 10) * pMax;

                if (index - maxLength < index2 - minLength)
                    index = index2 - minLength + maxLength;
                else
                    index2 = index - maxLength + minLength;

                int[] nCode = CalCode(index - maxLength, n);

                if (code.Length == nCode.Length && CompareArray(code, nCode))
                    return (int)index - maxLength;
            }
        }

        static bool CompareArray(int[] a, int[] b)
        {
            for (int i = 0; i < a.Length; i++)
                if (a[i] != b[i])
                    return false;

            return true;
        }

        static long GetNext(long n, int luckCount)
        {
            long nIndex = n + 1;

            while (true)
            {
                int count = GetLuckCount(nIndex);

                if (count == luckCount)
                    return nIndex;
                else if (count > luckCount)
                {
                    int pIndex = 0;
                    while (nIndex % 10 != 4 && nIndex % 10 != 7)
                    {
                        nIndex /= 10;
                        pIndex++;
                    }

                    nIndex = (nIndex + 1) * Power10[pIndex];
                }
                else
                {
                    int pIndex = 0;
                    while (nIndex % 10 == 4 || nIndex % 10 == 7)
                    {
                        nIndex /= 10;
                        pIndex++;
                    }

                    while (!Check(nIndex))
                        nIndex++;

                    nIndex = nIndex * Power10[pIndex] + (Power10[pIndex] - 1) / 9 * 4;
                }
            }
        }

        static bool Check(long index)
        {
            while (index % 10 == 0)
                index /= 10;

            return index % 10 == 4 || index % 10 == 7;
        }

        static int CompareValue(int[] a, int[] b, int index)
        {
            for (int i = 0; i <= index; i++)
                if (a[i] != b[i])
                    return a[i].CompareTo(b[i]);

            return 0;
        }

        static int CalLength(int[] code, int max)
        {
            int length = 0;

            for (int i = 0; i < code.Length; i++)
            {
                if(code[i] == max)
                    break;

                length += (int)Power10[code[i] / 10];
            }

            return length;
        }

        static int[] CalCode(long m, long n)
        {
            List<int> result = new List<int>();
            int add = 0, count = GetLuckCount(m - 1);

            while (n != 0)
            {
                if (n < Power10[add])
                {
                    add--;
                    count -= 10;
                }
                else if (m % Power10[add + 1] == 0 && Power10[add + 1] <= n)
                {
                    add++;
                    count += 10;
                }
                else
                {
                    long nIndex = m;

                    while (nIndex % 10 == 0)
                        nIndex /= 10;

                    int mod = (int)(nIndex % 10);

                    if (mod == 4 || mod == 7)
                        count++;
                    else if (mod == 5 || mod == 8)
                        count--;

                    result.Add(count);
                    m += (int)Power10[add];
                    n -= (int)Power10[add];
                }
            }

            return result.ToArray();
        }

        static int GetLuckCount(long m)
        {
            int count = 0;
            while (m > 0)
            {
                if (m % 10 == 4 || m % 10 == 7)
                    count++;

                m /= 10;
            }

            return count;
        }
    }
}


using System;
using System.Globalization;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace Codeforces
{
    class Program : ProgramBase
    {
        private const long commonMod = 1000000007;

        static void Main(string[] args)
        {
            var p = new Program();
            var x = p.Solve();
            p.Out(x);
        }
        object Solve()
        {
            var n = ReadLong();
            if (n == 1)
                return "1 1\n1";
            return 2 * (n - 1) + " 2\n1 2";
        }

        class Trie
        {

        }

        class Node {
            public Node()
            {
                Children = new Node[10];
            }
            public Node[] Children { get; set; }
            public int Count { get; set; }
            public char Letter { get; set; }

            public string Final { get; set; }
            private int Rev = -1;

            public void RecursePlus()
            {
                if (Rev != -1)
                    Count++;
                for (int i = 0; i < 10; i++)
                {
                    if (Children[i] != null)
                    {
                        Children[i].RecursePlus();
                    }
                }
            }
            public void Insert(string s, int begin, int rev)
            {
                //Count++;
                if (rev != Rev)
                {
                    if (Rev != -1)
                        Count++;
                    Rev = rev;
                }
                if (begin == s.Length)
                {
                    Final = s;
                    return;
                }
                if (Children[s[begin] - '0'] == null)
                    Children[s[begin] - '0'] = new Node();
                Children[s[begin] - '0'].Insert(s, begin + 1, rev);
            }

            public void Recurse(Dictionary<string, string> dct, List<char> sofar)
            {
                if (Count == 1)
                    this.SetAns(dct, new string(sofar.ToArray()));
                else
                    for (int i = 0; i < 10; i++)
                    {
                        if (Children[i] != null)
                        {
                            sofar.Add(i.ToString()[0]);
                            Children[i].Recurse(dct, sofar);
                            sofar.RemoveAt(sofar.Count - 1);
                        }
                    }
            }
            public void SetAns(Dictionary<string, string> dct, string ans) {
                if (Final != null)
                {
                    if (!dct.ContainsKey(Final) || dct[Final].Length > ans.Length)
                        dct[Final] = ans;
                    return;
                }
                for (int i = 0; i < 10; i++)
                {
                    if (Children[i] != null)
                    {
                        Children[i].SetAns(dct, ans);
                        return;
                    }
                }
            }
        }

        class End
        {
            public long Val { get; set; }
            public bool Left { get; set; }
        }
    }

    abstract class ProgramBase
    {
        bool? prod = null;
        StreamReader f;
        Queue<string> tokens;
        protected string FileName { private get; set; }

        protected string Read()
        {
            if (f == null)
                f = string.IsNullOrEmpty(FileName)
                    ? new StreamReader(Console.OpenStandardInput(1024 * 10), Encoding.ASCII, false, 1024 * 10)
                    : new StreamReader((GetProd() ? "" : "c:\\dev\\") + FileName);
            return f.ReadLine();
        }

        protected string ReadToken()
        {
            if (tokens == null || tokens.Count == 0)
                tokens = new Queue<string>(Read().Split(' '));
            return tokens.Dequeue();
        }

        protected long ReadLong() { return long.Parse(ReadToken()); }

        protected long[] ReadLongs()
        {
            var s = Read();
            if (s == "")
                return new long[0];
            //var i = s.IndexOf(' ');
            //return new[] { long.Parse(s.Substring(0, i)), long.Parse(s.Substring(i + 1)) };
            var tokens = s.Split(' ');
            var result = new long[tokens.Length];
            for (int i = 0; i < tokens.Length; i++)
                result[i] = long.Parse(tokens[i]);
            return result;
        }

        public void Out(object r)
        {
            if (string.IsNullOrEmpty(FileName))
                Console.WriteLine(r);
            else if (GetProd())
                File.WriteAllText(FileName, r.ToString());
            else
                Console.WriteLine(r);
        }

        private bool GetProd()
        {

            if (!prod.HasValue)
                try
                {
                    prod = Environment.MachineName != "RENADEEN-W7";
                }
                catch (Exception)
                {
                    prod = true;
                }
            return prod.Value;
        }
    }

    public static class Huj
    {
        public static T MinBy<T>(this IEnumerable<T> source, Func<T, double> func) where T : class
        {
            T result = null;
            var min = double.MaxValue;
            foreach (var item in source)
            {
                var current = func(item);
                if (min > current)
                {
                    min = current;
                    result = item;
                }
            }
            return result;
        }

        public static T MaxBy<T>(this IEnumerable<T> source, Func<T, double> func, T defaultValue = default(T))
        {
            T result = defaultValue;
            var max = double.MinValue;
            foreach (var item in source)
            {
                var current = func(item);
                if (max < current)
                {
                    max = current;
                    result = item;
                }
            }
            return result;
        }

        public static string JoinStrings(this IEnumerable<string> s, string d) { return string.Join(d, s.ToArray()); }

        public static string JoinStrings(this IEnumerable<int> s, string d) { return s.Select(x => x.ToString()).JoinStrings(d); }
        public static string JoinStrings(this IEnumerable<long> s, string d) { return s.Select(x => x.ToString()).JoinStrings(d); }
    }

}


using System;
 using System.CodeDom;
 using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;

namespace CF
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            using (var sr = new InputReader(Console.In))
//			using (var sr = new InputReader(new StreamReader("input.txt")))
            using (var sw = Console.Out)
                //using (var sw = new StreamWriter("output.txt"))
            using (var task = new Task(sr, sw)) {
                task.Solve();
//                Console.ReadKey();
            }
        }
    }

    internal class Task : IDisposable
    {
        private readonly InputReader sr;
        private readonly TextWriter sw;
        private bool isDispose;

        public Task(InputReader sr, TextWriter sw)
        {
            this.sr = sr;
            this.sw = sw;
        }

        public void Solve()
        {
            var a = sr.NextInt32();
            var s = 2 * a - 1;

            sw.WriteLine(s + " 2");
            sw.WriteLine("1 2");
        }

        ~Task()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!isDispose) {
                if (disposing) {
                    if(sr != null)
                        sr.Dispose();

                    if(sw != null)
                        sw.Dispose();
                }

                isDispose = true;
            }
        }
    }
}

internal class InputReader : IDisposable
{
    private bool isDispose;
    private readonly TextReader sr;
    private string[] buffer;
    private int seek;

    public InputReader(TextReader stream)
    {
        sr = stream;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public string NextString()
    {
        var result = sr.ReadLine();
        return result;
    }

    public int NextInt32()
    {
        return Int32.Parse(ReadNextToken());
    }

    private string ReadNextToken()
    {
        if (buffer == null || seek == buffer.Length) {
            seek = 0;
            buffer = NextSplitStrings();
        }

        return buffer[seek++];
    }

    public long NextInt64()
    {
        return Int64.Parse(ReadNextToken());
    }

    public int[] ReadArrayOfInt32()
    {
        return ReadArray(Int32.Parse);
    }

    public long[] ReadArrayOfInt64()
    {
        return ReadArray(Int64.Parse);
    }

    public string[] NextSplitStrings()
    {
        return NextString()
            .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
    }

    public T[] ReadArray<T>(Func<string, CultureInfo, T> func)
    {
        return NextSplitStrings()
            .Select(s => func(s, CultureInfo.InvariantCulture))
            .ToArray();
    }

    public T[] ReadArrayFromString<T>(Func<string, CultureInfo, T> func, string str)
    {
        return
            str.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(s => func(s, CultureInfo.InvariantCulture))
                .ToArray();
    }

    protected void Dispose(bool dispose)
    {
        if (!isDispose)
        {
            if (dispose)
                sr.Close();

            isDispose = true;
        }
    }

    ~InputReader()
    {
        Dispose(false);
    }
}


#define Online

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.IO;
using System.Numerics;

namespace CF
{
    delegate double F(double x);
    delegate decimal Fdec(decimal x);

    partial class Program
    {

        static void Main(string[] args)
        {

#if FileIO
            StreamReader sr = new StreamReader("nosimple.in");
            StreamWriter sw = new StreamWriter("nosimple.out");
            Console.SetIn(sr);
            Console.SetOut(sw);
#endif

            C();

#if Online
            Console.ReadLine();
#endif

#if FileIO
            sr.Close();
            sw.Close();
#endif
        }

        static void A()
        {

        }

        static void B()
        {

        }

        static void C()
        {
            long n, m, k;
            ReadArray(' ');
            n = NextLong();
            m = NextLong();
            k = NextLong();
            const long mod = 1000 * 1000 * 1000 + 7;
            long left, right, mid;
            right = m / (k - 1);
            left = 0;
            while (left < right)
            {
                mid = left + (right - left) / 2;

                if (n - k * mid <= m - (k - 1) * mid)
                {
                    right = mid;
                }
                else
                {
                    left = mid + 1;
                }
            }
            if (n - k * left < m - (k - 1) * left)
                left--;

            long rem = m - (k - 1) * left;
            long ans = MyMath.BinPow(2, rem / k, mod);
            ans--;
            ans = (ans * 2 * k) % mod;
            ans += (rem % k + left * (k - 1)) % mod;
            Console.WriteLine(ans);
        }

        static void D()
        {

        }

        static void E()
        {

        }

        static void TestGen()
        {

        }

    }

    public static class MyMath
    {
        public static long BinPow(long a, long n, long mod)
        {
            long res = 1;
            while (n > 0)
            {
                if ((n & 1) == 1)
                {
                    res = (res * a) % mod;
                }
                a = (a * a) % mod;
                n >>= 1;
            }
            return res;
        }

        public static long GCD(long a, long b)
        {
            while (b != 0) b = a % (a = b);
            return a;
        }

        public static int GCD(int a, int b)
        {
            while (b != 0) b = a % (a = b);
            return a;
        }

        public static long LCM(long a, long b)
        {
            return (a * b) / GCD(a, b);
        }

        public static int LCM(int a, int b)
        {
            return (a * b) / GCD(a, b);
        }
    }

    static class ArrayUtils
    {
        public static int BinarySearch(int[] a, int val)
        {
            int left = 0;
            int right = a.Length - 1;
            int mid;

            while (left < right)
            {
                mid = left + ((right - left) >> 1);
                if (val <= a[mid])
                {
                    right = mid;
                }
                else
                {
                    left = mid + 1;
                }
            }

            if (a[left] == val)
                return left;
            else
                return -1;
        }

        public static double Bisection(F f, double left, double right, double eps)
        {
            double mid;
            while (right - left > eps)
            {
                mid = left + ((right - left) / 2d);
                if (Math.Sign(f(mid)) != Math.Sign(f(left)))
                    right = mid;
                else
                    left = mid;
            }
            return (left + right) / 2d;
        }

        public static decimal TernarySearchDec(Fdec f, decimal eps, decimal l, decimal r, bool isMax)
        {
            decimal m1, m2;
            while (r - l > eps)
            {
                m1 = l + (r - l) / 3m;
                m2 = r - (r - l) / 3m;
                if (f(m1) < f(m2))
                    if (isMax)
                        l = m1;
                    else
                        r = m2;
                else
                    if (isMax)
                        r = m2;
                    else
                        l = m1;
            }
            return r;
        }

        public static double TernarySearch(F f, double eps, double l, double r, bool isMax)
        {
            double m1, m2;
            while (r - l > eps)
            {
                m1 = l + (r - l) / 3d;
                m2 = r - (r - l) / 3d;
                if (f(m1) < f(m2))
                    if (isMax)
                        l = m1;
                    else
                        r = m2;
                else
                    if (isMax)
                        r = m2;
                    else
                        l = m1;
            }
            return r;
        }

        public static void Merge<T>(T[] A, int p, int q, int r, T[] L, T[] R, Comparison<T> comp)
        {
            for (int i = p; i <= q; i++)
                L[i] = A[i];
            for (int i = q + 1; i <= r; i++)
                R[i] = A[i];

            for (int k = p, i = p, j = q + 1; k <= r; k++)
            {
                if (i > q)
                {
                    for (; k <= r; k++, j++)
                        A[k] = R[j];
                    return;
                }
                if (j > r)
                {
                    for (; k <= r; k++, i++)
                        A[k] = L[i];
                    return;
                }
                if (comp(L[i], R[j]) <= 0)
                {
                    A[k] = L[i];
                    i++;
                }
                else
                {
                    A[k] = R[j];
                    j++;
                }
            }
        }

        public static void Merge_Sort<T>(T[] A, int p, int r, T[] L, T[] R, Comparison<T> comp)
        {
            if (p >= r) return;
            int q = p + ((r - p) >> 1);
            Merge_Sort(A, p, q, L, R, comp);
            Merge_Sort(A, q + 1, r, L, R, comp);
            Merge(A, p, q, r, L, R, comp);
        }

        public static void Merge<T>(T[] A, int p, int q, int r, T[] L, T[] R) where T : IComparable<T>
        {
            for (int i = p; i <= q; i++)
                L[i] = A[i];
            for (int i = q + 1; i <= r; i++)
                R[i] = A[i];

            for (int k = p, i = p, j = q + 1; k <= r; k++)
            {
                if (i > q)
                {
                    for (; k <= r; k++, j++)
                        A[k] = R[j];
                    return;
                }
                if (j > r)
                {
                    for (; k <= r; k++, i++)
                        A[k] = L[i];
                    return;
                }
                if (L[i].CompareTo(R[j]) <= 0)
                {
                    A[k] = L[i];
                    i++;
                }
                else
                {
                    A[k] = R[j];
                    j++;
                }
            }
        }

        public static void Merge_Sort<T>(T[] A, int p, int r, T[] L, T[] R) where T : IComparable<T>
        {
            if (p >= r) return;
            int q = p + ((r - p) >> 1);
            Merge_Sort(A, p, q, L, R);
            Merge_Sort(A, q + 1, r, L, R);
            Merge(A, p, q, r, L, R);
        }

        public static void Merge_Sort1<T>(T[] A, int p, int r, T[] L, T[] R) where T : IComparable<T>
        {
            int k = 1;
            while (k < r - p + 1)
            {
                int i = 0;
                while (i < r)
                {
                    int _r = Math.Min(i + 2 * k - 1, r);
                    int q = Math.Min(i + k - 1, r);
                    Merge(A, i, q, _r, L, R);
                    i += 2 * k;
                }
                k <<= 1;
            }
        }

        public static void Merge_Sort1<T>(T[] A, int p, int r, T[] L, T[] R, Comparison<T> comp)
        {
            int k = 1;
            while (k < r - p + 1)
            {
                int i = 0;
                while (i < r)
                {
                    int _r = Math.Min(i + 2 * k - 1, r);
                    int q = Math.Min(i + k - 1, r);
                    Merge(A, i, q, _r, L, R, comp);
                    i += 2 * k;
                }
                k <<= 1;
            }
        }

        static void Shake<T>(T[] a)
        {
            Random rnd = new Random(Environment.TickCount);
            T temp;
            int b;
            for (int i = 0; i < a.Length; i++)
            {
                b = rnd.Next(i, a.Length);
                temp = a[b];
                a[b] = a[i];
                a[i] = temp;
            }
        }
    }

    partial class Program
    {
        static string[] tokens;
        static int cur_token = 0;

        static void ReadArray(char sep)
        {
            cur_token = 0;
            tokens = Console.ReadLine().Split(sep);
        }

        static int ReadInt()
        {
            return int.Parse(Console.ReadLine());
        }

        static long ReadLong()
        {
            return long.Parse(Console.ReadLine());
        }

        static int NextInt()
        {
            return int.Parse(tokens[cur_token++]);
        }

        static long NextLong()
        {
            return long.Parse(tokens[cur_token++]);
        }

        static double NextDouble()
        {
            return double.Parse(tokens[cur_token++]);
        }

        static decimal NextDecimal()
        {
            return decimal.Parse(tokens[cur_token++]);
        }

        static string NextToken()
        {
            return tokens[cur_token++];
        }

        static string ReadLine()
        {
            return Console.ReadLine();
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] s = Console.ReadLine().Split().Select(int.Parse).ToArray();
            long n = s[0], m = s[1], k = s[2], ans = 0, z = 0;
            long er = n - m, kp = k;
            bool b=false;
            for (int i = 1; i <= n; i++)
            {
                z++;
                if (i == (n - k * er + 1))
                    b = true;
                if (z < k)
                {
                    ans++;
                   // z++;
                }
                else
                {
                    if (b==true)
                    {
                        z = 0;
                        //er--;
                    }
                    else
                    {
                        ans = (ans + 1) * 2;
                        z = 0;
                    }
                }
            }
            if (m == 0) ans = 0;
            Console.WriteLine(ans % 1000000009);
              //  Console.Read();

            }
        }
    }


using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

public class taskA
{
    public class MyReader
    {
        private TextReader instream;

        public int[] ReadIntArray()
        {
            string inp = instream.ReadLine().Trim();
            string[] spl = inp.Split(' ');

            int[] a = new int[spl.Length];
            for (int i = 0; i < a.Length; i++)
                a[i] = int.Parse(spl[i]);
            return a;
        }

        public long[] ReadLongArray()
        {
            string inp = instream.ReadLine().Trim();
            string[] spl = inp.Split(' ');

            long[] a = new long[spl.Length];
            for (int i = 0; i < a.Length; i++)
                a[i] = long.Parse(spl[i]);
            return a;
        }

        public double[] ReadDoubleArray()
        {
            string inp = instream.ReadLine().Trim();
            string[] spl = inp.Split(' ');

            double[] a = new double[spl.Length];

            System.Globalization.NumberFormatInfo nfi = new System.Globalization.NumberFormatInfo();
            nfi.NumberDecimalSeparator = ".";
            for (int i = 0; i < a.Length; i++)
                a[i] = double.Parse(spl[i], nfi);
            return a;
        }

        public int ReadInt()
        {
            return int.Parse(instream.ReadLine());
        }

        public long ReadLong()
        {
            return long.Parse(instream.ReadLine());
        }

        public void SetInStream(TextReader textReader)
        {
            this.instream = textReader;
        }

        internal string ReadLine()
        {
            return instream.ReadLine();
        }
    }

    static void Main(string[] args)
    {
        MyReader instream = new MyReader();
        instream.SetInStream(Console.In);

        TextWriter outstream = Console.Out;

        solve(instream, outstream);

    }

    private static void solve(MyReader instream, TextWriter outstream)
    {
        long[] nmk = instream.ReadLongArray();

        long n = nmk[0];
        long m = nmk[1];
        long k = nmk[2];

        long mod = 1000000009;

        long res=0;
        if (m == 0)
            res = 0;
        else
        {
            long blocks = n / k;
            if (blocks * (k - 1) <=m )
            {
                res = m;
            }
            else
            {
                blocks = n - m;

                long y = n - k * (n - m);
                //blocks*(k-1)

                long cnt = y / k;
                long free = y - cnt * k;

                res = powmod(2, cnt + 1, mod);

                res = (res - 2 + mod) % mod;

                res = res * k % mod;

                res = (res + free) % mod;
                res = (res + (blocks * (k - 1) % mod)) % mod;
            }
        }
        outstream.WriteLine(res);
    }

    private static long powmod(int v, long pow, long mod)
    {
        long res = 1;
        long b = v;
        while (pow > 0)
        {
            if ((pow & 1) == 1) res = (res * b) % mod;

            b = (b * b) % mod;
            pow >>= 1;
        }
        return res;
    }

}


#define Online

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.IO;
using System.Numerics;

namespace CF
{
    delegate double F(double x);
    delegate decimal Fdec(decimal x);

    partial class Program
    {

        static void Main(string[] args)
        {

#if FileIO
            StreamReader sr = new StreamReader("nosimple.in");
            StreamWriter sw = new StreamWriter("nosimple.out");
            Console.SetIn(sr);
            Console.SetOut(sw);
#endif

            C();

#if Online
            Console.ReadLine();
#endif

#if FileIO
            sr.Close();
            sw.Close();
#endif
        }

        static void A()
        {

        }

        static void B()
        {

        }

        static void C()
        {
            long n, m, k;
            ReadArray(' ');
            n = NextLong();
            m = NextLong();
            k = NextLong();
            const long mod = 1000 * 1000 * 1000 + 9;
            long left, right, mid;
            right = m / (k - 1);
            left = 0;
            while (left < right)
            {
                mid = left + (right - left) / 2;

                if (n - k * mid <= m - (k - 1) * mid)
                {
                    right = mid;
                }
                else
                {
                    left = mid + 1;
                }
            }
            if (n - k * left < m - (k - 1) * left)
                left--;

            long rem = m - (k - 1) * left;
            long ans = MyMath.BinPow(2, rem / k, mod);
            ans--;
            ans = (ans * 2 * k) % mod;
            ans += (rem % k + left * (k - 1)) % mod;
            Console.WriteLine(ans);
        }

        static void D()
        {

        }

        static void E()
        {

        }

        static void TestGen()
        {

        }

    }

    public static class MyMath
    {
        public static long BinPow(long a, long n, long mod)
        {
            long res = 1;
            while (n > 0)
            {
                if ((n & 1) == 1)
                {
                    res = (res * a) % mod;
                }
                a = (a * a) % mod;
                n >>= 1;
            }
            return res;
        }

        public static long GCD(long a, long b)
        {
            while (b != 0) b = a % (a = b);
            return a;
        }

        public static int GCD(int a, int b)
        {
            while (b != 0) b = a % (a = b);
            return a;
        }

        public static long LCM(long a, long b)
        {
            return (a * b) / GCD(a, b);
        }

        public static int LCM(int a, int b)
        {
            return (a * b) / GCD(a, b);
        }
    }

    static class ArrayUtils
    {
        public static int BinarySearch(int[] a, int val)
        {
            int left = 0;
            int right = a.Length - 1;
            int mid;

            while (left < right)
            {
                mid = left + ((right - left) >> 1);
                if (val <= a[mid])
                {
                    right = mid;
                }
                else
                {
                    left = mid + 1;
                }
            }

            if (a[left] == val)
                return left;
            else
                return -1;
        }

        public static double Bisection(F f, double left, double right, double eps)
        {
            double mid;
            while (right - left > eps)
            {
                mid = left + ((right - left) / 2d);
                if (Math.Sign(f(mid)) != Math.Sign(f(left)))
                    right = mid;
                else
                    left = mid;
            }
            return (left + right) / 2d;
        }

        public static decimal TernarySearchDec(Fdec f, decimal eps, decimal l, decimal r, bool isMax)
        {
            decimal m1, m2;
            while (r - l > eps)
            {
                m1 = l + (r - l) / 3m;
                m2 = r - (r - l) / 3m;
                if (f(m1) < f(m2))
                    if (isMax)
                        l = m1;
                    else
                        r = m2;
                else
                    if (isMax)
                        r = m2;
                    else
                        l = m1;
            }
            return r;
        }

        public static double TernarySearch(F f, double eps, double l, double r, bool isMax)
        {
            double m1, m2;
            while (r - l > eps)
            {
                m1 = l + (r - l) / 3d;
                m2 = r - (r - l) / 3d;
                if (f(m1) < f(m2))
                    if (isMax)
                        l = m1;
                    else
                        r = m2;
                else
                    if (isMax)
                        r = m2;
                    else
                        l = m1;
            }
            return r;
        }

        public static void Merge<T>(T[] A, int p, int q, int r, T[] L, T[] R, Comparison<T> comp)
        {
            for (int i = p; i <= q; i++)
                L[i] = A[i];
            for (int i = q + 1; i <= r; i++)
                R[i] = A[i];

            for (int k = p, i = p, j = q + 1; k <= r; k++)
            {
                if (i > q)
                {
                    for (; k <= r; k++, j++)
                        A[k] = R[j];
                    return;
                }
                if (j > r)
                {
                    for (; k <= r; k++, i++)
                        A[k] = L[i];
                    return;
                }
                if (comp(L[i], R[j]) <= 0)
                {
                    A[k] = L[i];
                    i++;
                }
                else
                {
                    A[k] = R[j];
                    j++;
                }
            }
        }

        public static void Merge_Sort<T>(T[] A, int p, int r, T[] L, T[] R, Comparison<T> comp)
        {
            if (p >= r) return;
            int q = p + ((r - p) >> 1);
            Merge_Sort(A, p, q, L, R, comp);
            Merge_Sort(A, q + 1, r, L, R, comp);
            Merge(A, p, q, r, L, R, comp);
        }

        public static void Merge<T>(T[] A, int p, int q, int r, T[] L, T[] R) where T : IComparable<T>
        {
            for (int i = p; i <= q; i++)
                L[i] = A[i];
            for (int i = q + 1; i <= r; i++)
                R[i] = A[i];

            for (int k = p, i = p, j = q + 1; k <= r; k++)
            {
                if (i > q)
                {
                    for (; k <= r; k++, j++)
                        A[k] = R[j];
                    return;
                }
                if (j > r)
                {
                    for (; k <= r; k++, i++)
                        A[k] = L[i];
                    return;
                }
                if (L[i].CompareTo(R[j]) <= 0)
                {
                    A[k] = L[i];
                    i++;
                }
                else
                {
                    A[k] = R[j];
                    j++;
                }
            }
        }

        public static void Merge_Sort<T>(T[] A, int p, int r, T[] L, T[] R) where T : IComparable<T>
        {
            if (p >= r) return;
            int q = p + ((r - p) >> 1);
            Merge_Sort(A, p, q, L, R);
            Merge_Sort(A, q + 1, r, L, R);
            Merge(A, p, q, r, L, R);
        }

        public static void Merge_Sort1<T>(T[] A, int p, int r, T[] L, T[] R) where T : IComparable<T>
        {
            int k = 1;
            while (k < r - p + 1)
            {
                int i = 0;
                while (i < r)
                {
                    int _r = Math.Min(i + 2 * k - 1, r);
                    int q = Math.Min(i + k - 1, r);
                    Merge(A, i, q, _r, L, R);
                    i += 2 * k;
                }
                k <<= 1;
            }
        }

        public static void Merge_Sort1<T>(T[] A, int p, int r, T[] L, T[] R, Comparison<T> comp)
        {
            int k = 1;
            while (k < r - p + 1)
            {
                int i = 0;
                while (i < r)
                {
                    int _r = Math.Min(i + 2 * k - 1, r);
                    int q = Math.Min(i + k - 1, r);
                    Merge(A, i, q, _r, L, R, comp);
                    i += 2 * k;
                }
                k <<= 1;
            }
        }

        static void Shake<T>(T[] a)
        {
            Random rnd = new Random(Environment.TickCount);
            T temp;
            int b;
            for (int i = 0; i < a.Length; i++)
            {
                b = rnd.Next(i, a.Length);
                temp = a[b];
                a[b] = a[i];
                a[i] = temp;
            }
        }
    }

    partial class Program
    {
        static string[] tokens;
        static int cur_token = 0;

        static void ReadArray(char sep)
        {
            cur_token = 0;
            tokens = Console.ReadLine().Split(sep);
        }

        static int ReadInt()
        {
            return int.Parse(Console.ReadLine());
        }

        static long ReadLong()
        {
            return long.Parse(Console.ReadLine());
        }

        static int NextInt()
        {
            return int.Parse(tokens[cur_token++]);
        }

        static long NextLong()
        {
            return long.Parse(tokens[cur_token++]);
        }

        static double NextDouble()
        {
            return double.Parse(tokens[cur_token++]);
        }

        static decimal NextDecimal()
        {
            return decimal.Parse(tokens[cur_token++]);
        }

        static string NextToken()
        {
            return tokens[cur_token++];
        }

        static string ReadLine()
        {
            return Console.ReadLine();
        }
    }
}


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

namespace SP.Solutions.CodeForces.c338_196_1
{
	public class ProgramA
	{
        private const long Mod = 1000000009;

        public static long FastModPow(long a, long n, long mod)
        {
            if (n == 0) return 1;
            if (n == 1) return a%mod;
            var res = FastModPow(a, n/2, mod);
            res = res*res%mod;
            if ((n & 1) == 1) res = res*a%mod;
            return res;
        }

		public static void Main()
		{
			checked
			{
			    var s = Console.ReadLine().Split(' ').Select(long.Parse).ToArray();
			    var n = s[0];
			    var correct = s[1];
			    var k = s[2];
			    var wrong = n - correct;

			    var afterCorrect = (k - 1)*wrong;
			    afterCorrect = Math.Min(n, afterCorrect);
			    afterCorrect = Math.Min(afterCorrect, correct);
			    correct -= afterCorrect;
			    if (correct < 0) correct = 0;

			    var doubles = correct/k;

			    var res = 2*(FastModPow(2, doubles, Mod) - 1);
			    res = res*k%Mod;
			    res += correct%k + afterCorrect;
			    res %= Mod;

                Console.WriteLine(res);
			}
		}
	}
}


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Threading;

namespace Temp
{
    public class PointInt
    {
        public long X;

        public long Y;

        public PointInt(long x, long y)
        {
            this.X = x;
            this.Y = y;
        }

        public PointInt(PointInt head)
            : this(head.X, head.Y)
        {
        }

        public static PointInt operator +(PointInt a, PointInt b)
        {
            return new PointInt(a.X + b.X, a.Y + b.Y);
        }

        public static PointInt operator -(PointInt a, PointInt b)
        {
            return new PointInt(a.X - b.X, a.Y - b.Y);
        }

        public static PointInt operator *(PointInt a, long k)
        {
            return new PointInt(k * a.X, k * a.Y);
        }

        public static PointInt operator *(long k, PointInt a)
        {
            return new PointInt(k * a.X, k * a.Y);
        }

        public bool IsInsideRectangle(long l, long b, long r, long t)
        {
            return (l <= X) && (X <= r) && (b <= Y) && (Y <= t);
        }

        public bool Equals(PointInt other)
        {
            if (ReferenceEquals(null, other))
            {
                return false;
            }
            if (ReferenceEquals(this, other))
            {
                return true;
            }
            return other.X == this.X && other.Y == this.Y;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != typeof(PointInt))
            {
                return false;
            }
            return Equals((PointInt)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (this.X.GetHashCode() * 397) ^ this.Y.GetHashCode();
            }
        }
    }

    public class Point2DReal
    {
        public double X;

        public double Y;

        public Point2DReal(double x, double y)
        {
            this.X = x;
            this.Y = y;
        }

        public Point2DReal(Point2DReal head)
            : this(head.X, head.Y)
        {
        }

        public static Point2DReal operator +(Point2DReal a, Point2DReal b)
        {
            return new Point2DReal(a.X + b.X, a.Y + b.Y);
        }

        public static Point2DReal operator -(Point2DReal a, Point2DReal b)
        {
            return new Point2DReal(a.X - b.X, a.Y - b.Y);
        }

        public static Point2DReal operator *(Point2DReal a, double k)
        {
            return new Point2DReal(k * a.X, k * a.Y);
        }

        public static Point2DReal operator *(double k, Point2DReal a)
        {
            return new Point2DReal(k * a.X, k * a.Y);
        }

        public double Dist(Point2DReal p)
        {
            return Math.Sqrt((p.X - X) * (p.X - X) + (p.Y - Y) * (p.Y - Y));
        }

        public bool IsInsideRectangle(double l, double b, double r, double t)
        {
            return (l <= X) && (X <= r) && (b <= Y) && (Y <= t);
        }
    }

    internal class LineInt
    {
        public LineInt(PointInt a, PointInt b)
        {
            A = a.Y - b.Y;
            B = b.X - a.X;
            C = a.X * b.Y - a.Y * b.X;
        }

        public long A, B, C;

        public bool ContainsPoint(PointInt p)
        {
            return A * p.X + B * p.Y + C == 0;
        }

        public int Sign(PointInt p)
        {
            return Math.Sign(A * p.X + B * p.Y + C);
        }
    }

    internal static class Geometry
    {
        public static long VectInt(PointInt a, PointInt b)
        {
            return a.X * b.Y - a.Y * b.X;
        }

        public static long VectInt(PointInt a, PointInt b, PointInt c)
        {
            return (b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X);
        }
    }

    internal class MatrixInt
    {
        private readonly long[,] m_Matrix;

        public int Size
        {
            get { return m_Matrix.GetLength(0); }
        }

        public long Mod { get; private set; }

        public MatrixInt(int size, long mod = 0)
        {
            m_Matrix = new long[size,size];
            Mod = mod;
        }

        public MatrixInt(long[,] matrix, long mod = 0)
        {
            var size = matrix.GetLength(0);
            m_Matrix = new long[size,size];
            Array.Copy(matrix, m_Matrix, size * size);
            Mod = mod;

            if (mod != 0)
            {
                for (int i = 0; i < size; i++)
                {
                    for (int j = 0; j < size; j++)
                    {
                        m_Matrix[i, j] %= mod;
                    }
                }
            }
        }

        public static MatrixInt IdentityMatrix(int size, long mod = 0)
        {
            long[,] matrix = new long[size,size];

            for (int i = 0; i < size; i++)
            {
                matrix[i, i] = 1;
            }

            return new MatrixInt(matrix, mod);
        }

        public long this[int i, int j]
        {
            get { return m_Matrix[i, j]; }

            set { m_Matrix[i, j] = value; }
        }

        public static MatrixInt operator +(MatrixInt a, MatrixInt b)
        {
            int n = a.Size;
            long mod = Math.Max(a.Mod, b.Mod);
            long[,] c = new long[n,n];
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    c[i, j] = a[i, j] + b[i, j];
                }
            }

            if (mod > 0)
            {
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        c[i, j] %= mod;
                    }
                }
            }

            return new MatrixInt(c, mod);
        }

        public static MatrixInt operator *(MatrixInt a, MatrixInt b)
        {
            int n = a.Size;
            long mod = Math.Max(a.Mod, b.Mod);

            long[,] c = new long[n,n];

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    for (int k = 0; k < n; k++)
                    {
                        c[i, j] += a[i, k] * b[k, j];
                        if (mod > 0)
                        {
                            c[i, j] %= mod;
                        }
                    }
                }
            }

            return new MatrixInt(c, mod);
        }

        public void Print()
        {
            for (int i = 0; i < Size; i++)
            {
                for (int j = 0; j < Size; j++)
                {
                    Console.Write("{0} ", m_Matrix[i, j]);
                }
                Console.WriteLine();
            }
        }
    }

    public static class Permutations
    {
        private static readonly Random m_Random;

        static Permutations()
        {
            m_Random = new Random();
        }

        public static int[] GetRandomPermutation(int n)
        {
            int[] p = new int[n];
            for (int i = 0; i < n; i++)
            {
                p[i] = i;
            }

            for (int i = n - 1; i > 0; i--)
            {
                int j = m_Random.Next(i + 1);
                int tmp = p[i];
                p[i] = p[j];
                p[j] = tmp;
            }

            return p;
        }

        /*public static T[] Shuffle<T>(this T[] array)
        {
            int length = array.Length;
            int[] p = GetRandomPermutation(length);
            T[] result = new T[length];
            for (int i = 0; i < length; i++)
            {
                result[i] = array[p[i]];
            }

            return result;
        }*/

        /*public static T[] ShuffleSort<T>(this T[] array)
        {
            var result = array.Shuffle();
            Array.Sort(result);
            return result;
        }*/

        public static void Shuffle<T>(T[] array)
        {
            var n = array.Count();
            for (int i = n - 1; i > 0; i--)
            {
                int j = m_Random.Next(i + 1);
                T tmp = array[i];
                array[i] = array[j];
                array[j] = tmp;
            }
        }

        public static void ShuffleSort<T>(T[] array)
        {
            Shuffle(array);
            Array.Sort(array);
        }

        public static int[] Next(int[] p)
        {
            int n = p.Length;
            var next = new int[n];
            Array.Copy(p, next, n);

            int k = -1;
            for (int i = n - 1; i > 0; i--)
            {
                if (next[i - 1] < next[i])
                {
                    k = i - 1;
                    break;
                }
            }
            if (k == -1)
            {
                return null;
            }
            for (int i = n - 1; i >= 0; i--)
            {
                if (next[i] > next[k])
                {
                    var tmp = next[i];
                    next[i] = next[k];
                    next[k] = tmp;
                    break;
                }
            }
            for (int i = 1; i <= (n - k - 1) / 2; i++)
            {
                var tmp = next[k + i];
                next[k + i] = next[n - i];
                next[n - i] = tmp;
            }

            return next;
        }
    }

    internal static class Algebra
    {
        public static long Phi(long n)
        {
            long result = n;
            for (long i = 2; i * i <= n; i++)
            {
                if (n % i == 0)
                {
                    while (n % i == 0)
                    {
                        n /= i;
                    }

                    result -= result / i;
                }
            }

            if (n > 1)
            {
                result -= result / n;
            }

            return result;
        }

        public static long BinPower(long a, long n, long mod)
        {
            long result = 1;

            while (n > 0)
            {
                if ((n & 1) != 0)
                {
                    result = (result * a) % mod;
                }

                a = (a * a) % mod;
                n >>= 1;
            }

            return result;
        }

        public static MatrixInt MatrixBinPower(MatrixInt a, long n)
        {
            MatrixInt result = MatrixInt.IdentityMatrix(a.Size, a.Mod);

            while (n > 0)
            {
                if ((n & 1) != 0)
                {
                    result *= a;
                }

                a *= a;
                n >>= 1;
            }

            return result;
        }

        public static long Gcd(long a, long b)
        {
            return b == 0 ? a : Gcd(b, a % b);
        }

        public static long ExtendedGcd(long a, long b, out long x, out long y)
        {
            if (b == 0)
            {
                x = 1;
                y = 0;
                return a;
            }

            long x1;
            long y1;
            long d = ExtendedGcd(b, a % b, out x1, out y1);
            x = y1;
            y = x1 - (a / b) * y1;
            return d;
        }

        public static long Lcm(long a, long b)
        {
            return (a / Gcd(a, b)) * b;
        }

        public static bool[] GetPrimes(int n)
        {
            n = Math.Max(n, 2);
            bool[] prime = new bool[n + 1];
            for (int i = 2; i <= n; i++)
            {
                prime[i] = true;
            }

            for (int i = 2; i * i <= n; i++)
            {
                if (prime[i])
                {
                    if ((long)i * i <= n)
                    {
                        for (int j = i * i; j <= n; j += i)
                        {
                            prime[j] = false;
                        }
                    }
                }
            }

            return prime;
        }

        public static long GetFibonacciNumber(long n, long mod = 0)
        {
            long[,] matrix = new long[,] { { 0, 1 }, { 1, 1 } };

            MatrixInt result = MatrixBinPower(new MatrixInt(matrix, mod), n);

            return result[1, 1];
        }

        public static long[] GetFibonacciSequence(int n)
        {
            long[] result = new long[n];
            result[0] = result[1] = 1;

            for (int i = 2; i < n; i++)
            {
                result[i] = result[i - 1] + result[i - 2];
            }

            return result;
        }

        public static long GetInverseElement(long a, long mod)
        {
            long x, y;
            long g = ExtendedGcd(a, mod, out x, out y);

            if (g != 1)
            {
                return -1;
            }

            return ((x % mod) + mod) % mod;
        }

        public static long[] GetAllInverseElements(long n, long mod)
        {
            long[] result = new long[n];
            result[1] = 1;
            for (int i = 2; i < n; i++)
            {
                result[i] = (mod - (((mod / i) * result[mod % i]) % mod)) % mod;
            }

            return result;
        }

        public static int GetMinimalPrimeDivisor(int n)
        {
            for (int i = 2; i * i <= n; i++)
            {
                if (n % i == 0)
                {
                    return i;
                }
            }

            return n;
        }

        public static long Sqr(long x)
        {
            return x * x;
        }

        public static int SumOfDigits(long x, long baseMod = 10)
        {
            int res = 0;
            while (x > 0)
            {
                res += (int)(x % baseMod);
                x = x / baseMod;
            }
            return res;
        }
    }

    public static class OrderStatistic
    {
        public static T GetKthElement<T>(this IList<T> list, int k) where T : IComparable
        {
            return Select(list, 0, list.Count - 1, k);
        }

        private static T Select<T>(IList<T> list, int l, int r, int k) where T : IComparable
        {
            if (l == r)
                return list[l];

            T x = list[(l + r) / 2];
            var i = l;
            var j = r;
            do
            {
                while (list[i].CompareTo(x) < 0)
                    i++;
                while (list[j].CompareTo(x) > 0)
                    j--;
                if (i <= j)
                {
                    T tmp = list[i];
                    list[i] = list[j];
                    list[j] = tmp;

                    i++;
                    j--;
                }
            }
            while (i <= j);

            if (j < l)
                j++;
            if (k <= j - l + 1)
                return Select(list, l, j, k);
            return Select(list, j + 1, r, k - (j - l + 1));
        }
    }

    internal static class Reader
    {
        public static void Read<T>(out T v1)
        {
            var values = new T[1];
            Read(values);
            v1 = values[0];
        }

        public static void Read<T>(out T v1, out T v2)
        {
            var values = new T[2];
            Read(values);
            v1 = values[0];
            v2 = values[1];
        }

        public static void Read<T>(out T v1, out T v2, out T v3)
        {
            var values = new T[3];
            Read(values);
            v1 = values[0];
            v2 = values[1];
            v3 = values[2];
        }

        public static void Read<T>(out T v1, out T v2, out T v3, out T v4)
        {
            var values = new T[4];
            Read(values);
            v1 = values[0];
            v2 = values[1];
            v3 = values[2];
            v4 = values[3];
        }

        public static void Read<T>(out T v1, out T v2, out T v3, out T v4, out T v5)
        {
            var values = new T[5];
            Read(values);
            v1 = values[0];
            v2 = values[1];
            v3 = values[2];
            v4 = values[3];
            v5 = values[4];
        }

        public static void Read<T>(T[] values)
        {
            Read(values, values.Length);
        }

        public static void Read<T>(T[] values, int count)
        {
            // ReSharper disable PossibleNullReferenceException
            var list = Console.ReadLine().Split();
            // ReSharper restore PossibleNullReferenceException

            count = Math.Min(count, list.Length);

            var converter = TypeDescriptor.GetConverter(typeof(T));

            for (int i = 0; i < count; i++)
            {
                values[i] = (T)converter.ConvertFromString(list[i]);
            }
        }

        public static int[] ReadDigits()
        {
            // ReSharper disable AssignNullToNotNullAttribute
            return Console.ReadLine().Select(x => int.Parse(x.ToString(CultureInfo.InvariantCulture))).ToArray();
            // ReSharper restore AssignNullToNotNullAttribute
        }

        public static string ReadLine()
        {
            return Console.ReadLine();
        }
    }

    public interface IGraph
    {
        bool IsOriented { get; set; }

        int Vertices { get; set; }

        IList<int> this[int i] { get; }

        void AddEdge(int u, int v);

        void AddOrientedEdge(int u, int v);

        void AddNotOrientedEdge(int u, int v);
    }

    public class ListGraph : IGraph
    {
        private readonly List<int>[] m_Edges;

        public int Vertices { get; set; }

        public bool IsOriented { get; set; }

        public IList<int> this[int i]
        {
            get { return this.m_Edges[i]; }
        }

        public ListGraph(int vertices, bool isOriented = false)
        {
            this.Vertices = vertices;
            this.IsOriented = isOriented;

            this.m_Edges = new List<int>[vertices];

            for (int i = 0; i < vertices; i++)
            {
                this.m_Edges[i] = new List<int>();
            }
        }

        public void AddEdge(int u, int v)
        {
            this.AddOrientedEdge(u, v);
            if (!IsOriented)
            {
                this.AddOrientedEdge(v, u);
            }
        }

        public void AddNotOrientedEdge(int u, int v)
        {
            this.AddOrientedEdge(u, v);
            this.AddOrientedEdge(v, u);
        }

        public void AddOrientedEdge(int first, int second)
        {
            this.m_Edges[first].Add(second);
        }
    }

    public static class GraphAlgorithms
    {
        private static bool[] v;

        private static int[] a;

        private static int c;

        public static int[] Bfs(this IGraph graph, int start)
        {
            int[] d = new int[graph.Vertices];
            for (int i = 0; i < graph.Vertices; i++)
            {
                d[i] = -1;
            }

            Queue<int> queue = new Queue<int>();
            queue.Enqueue(start);
            d[start] = 0;

            while (queue.Count > 0)
            {
                int v = queue.Dequeue();
                foreach (int t in graph[v].Where(t => d[t] == -1))
                {
                    queue.Enqueue(t);
                    d[t] = d[v] + 1;
                }
            }

            return d;
        }

        public static int[] TopSort(this IGraph graph)
        {
            v = new bool[graph.Vertices];
            a = new int[graph.Vertices];
            c = graph.Vertices;

            for (int i = 0; i < graph.Vertices; i++)
            {
                if (!v[i])
                {
                    TopSortDfs(graph, i);
                }
            }

            return a;
        }

        private static void TopSortDfs(IGraph graph, int t)
        {
            v[t] = true;
            foreach (var next in graph[t])
            {
                if (!v[next])
                {
                    TopSortDfs(graph, next);
                }
            }
            c--;
            a[c] = t;
        }
    }

    internal class SimpleSumTable
    {
        private readonly int[,] m_Sum;

        public SimpleSumTable(int n, int m, int[,] table)
        {
            m_Sum = new int[n + 1,m + 1];

            for (int i = 1; i < n + 1; i++)
            {
                for (int j = 1; j < m + 1; j++)
                {
                    m_Sum[i, j] = m_Sum[i, j - 1] + m_Sum[i - 1, j] - m_Sum[i - 1, j - 1] + table[i - 1, j - 1];
                }
            }
        }

        public int GetSum(int l, int b, int r, int t)
        {
            return m_Sum[r + 1, t + 1] - m_Sum[r + 1, b] - m_Sum[l, t + 1] + m_Sum[l, b];
        }
    }

    internal class SegmentTreeSimpleInt<T>
    {
        public int Size { get; private set; }

        private readonly T[] m_Tree;

        private readonly Func<T, T, T> m_Operation;

        private readonly T m_Null;

        public SegmentTreeSimpleInt(int size, Func<T, T, T> operation, T nullElement, IList<T> array = null)
        {
            this.Size = size;
            this.m_Operation = operation;
            this.m_Null = nullElement;

            m_Tree = new T[4 * size];
            if (array != null)
            {
                this.Build(array, 1, 0, size - 1);
            }
        }

        private void Build(IList<T> array, int v, int tl, int tr)
        {
            if (tl == tr)
            {
                m_Tree[v] = array[tl];
            }
            else
            {
                int tm = (tl + tr) / 2;
                this.Build(array, 2 * v, tl, tm);
                this.Build(array, 2 * v + 1, tm + 1, tr);
                this.CalculateNode(v);
            }
        }

        public T GetSum(int l, int r)
        {
            return GetSum(1, 0, Size - 1, l, r);
        }

        private T GetSum(int v, int tl, int tr, int l, int r)
        {
            if (l > r)
            {
                return m_Null;
            }

            if (l == tl && r == tr)
            {
                return m_Tree[v];
            }

            int tm = (tl + tr) / 2;

            return this.m_Operation(
                GetSum(2 * v, tl, tm, l, Math.Min(r, tm)), GetSum(2 * v + 1, tm + 1, tr, Math.Max(l, tm + 1), r));
        }

        public void Update(int pos, T newValue)
        {
            Update(1, 0, Size - 1, pos, newValue);
        }

        private void Update(int v, int tl, int tr, int pos, T newValue)
        {
            if (tl == tr)
            {
                m_Tree[v] = newValue;
            }
            else
            {
                int tm = (tl + tr) / 2;
                if (pos <= tm)
                {
                    Update(2 * v, tl, tm, pos, newValue);
                }
                else
                {
                    Update(2 * v + 1, tm + 1, tr, pos, newValue);
                }
                this.CalculateNode(v);
            }
        }

        private void CalculateNode(int v)
        {
            m_Tree[v] = this.m_Operation(m_Tree[2 * v], m_Tree[2 * v + 1]);
        }
    }

    internal struct Pair<TFirst, TSecond>
    {
        public Pair(TFirst first, TSecond second)
            : this()
        {
            this.First = first;
            this.Second = second;
        }

        public TFirst First { set; get; }

        public TSecond Second { set; get; }

        private bool Equals(Pair<TFirst, TSecond> other)
        {
            return EqualityComparer<TFirst>.Default.Equals(this.First, other.First)
                   && EqualityComparer<TSecond>.Default.Equals(this.Second, other.Second);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
            {
                return false;
            }
            if (ReferenceEquals(this, obj))
            {
                return true;
            }
            if (obj.GetType() != this.GetType())
            {
                return false;
            }
            return Equals((Pair<TFirst, TSecond>)obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (EqualityComparer<TFirst>.Default.GetHashCode(this.First) * 397)
                       ^ EqualityComparer<TSecond>.Default.GetHashCode(this.Second);
            }
        }
    }

    internal class FenwickTreeInt64
    {
        public FenwickTreeInt64(int size)
        {
            this.m_Size = size;
            m_Tree = new long[size];
        }

        public FenwickTreeInt64(int size, IList<long> tree)
            : this(size)
        {
            for (int i = 0; i < size; i++)
            {
                Inc(i, tree[i]);
            }
        }

        public long Sum(int r)
        {
            long res = 0;
            for (; r >= 0; r = (r & (r + 1)) - 1)
            {
                res += m_Tree[r];
            }
            return res;
        }

        public long Sum(int l, int r)
        {
            return Sum(r) - Sum(l - 1);
        }

        public void Inc(int i, long x)
        {
            for (; i < m_Size; i = i | (i + 1))
            {
                m_Tree[i] += x;
            }
        }

        public void Set(int i, long x)
        {
            Inc(i, x - Sum(i, i));
        }

        private readonly int m_Size;

        private readonly long[] m_Tree;
    }

    internal class AccumulativeDictionary<TKey> : Dictionary<TKey, int>
    {
        public new void Add(TKey key, int value = 1)
        {
            if (this.ContainsKey(key))
            {
                base[key] += value;
            }
            else
            {
                base.Add(key, value);
            }
        }

        public new int this[TKey key]
        {
            get { return this.ContainsKey(key) ? base[key] : 0; }
            set { this.Add(key, value); }
        }
    }

    public class PriorityQueue<T>
    {
        public PriorityQueue(Comparison<T> comparison = null)
        {
            if (comparison == null)
            {
                if (typeof(T).GetInterfaces().Any(i => i == typeof(IComparable<T>)))
                {
                    m_Comparison = (a, b) => ((IComparable<T>)a).CompareTo(b);
                }
                else
                {
                    throw new ApplicationException("Add comparer");
                }
            }
            else
            {
                m_Comparison = comparison;
            }
        }

        public int Count { get; private set; }

        public void Enqueue(T item)
        {
            m_List.Add(item);
            m_Indexes.Add(item, this.Count);
            this.Count++;
            Up(this.Count);
        }

        public T Peek()
        {
            return m_List[0];
        }

        public T Dequeue()
        {
            if (this.Count > 0)
            {
                var result = m_List[0];

                Swap(0, this.Count - 1);
                m_Indexes.Remove(m_List[this.Count - 1]);
                m_List.RemoveAt(this.Count - 1);
                this.Count--;
                this.Down(1);

                return result;
            }
            throw new ApplicationException("Couldn't get element from empty queue");
        }

        public void Update(T item)
        {
            int index = m_Indexes[item];
            this.Up(index + 1);
        }

        private readonly List<T> m_List = new List<T>();

        private readonly Dictionary<T, int> m_Indexes = new Dictionary<T, int>();

        private readonly Comparison<T> m_Comparison;

        private void Up(int index)
        {
            while (index > 1 && m_Comparison.Invoke(m_List[index - 1], m_List[index / 2 - 1]) > 0)
            {
                this.Swap(index - 1, index / 2 - 1);

                index = index / 2;
            }
        }

        private void Down(int index)
        {
            while (2 * index <= this.Count && m_Comparison.Invoke(m_List[index - 1], m_List[2 * index - 1]) < 0
                   || 2 * index + 1 <= this.Count && m_Comparison.Invoke(m_List[index - 1], m_List[2 * index]) < 0)
            {
                if (2 * index + 1 > this.Count || m_Comparison.Invoke(m_List[2 * index - 1], m_List[2 * index]) > 0)
                {
                    this.Swap(index - 1, 2 * index - 1);
                    index = 2 * index;
                }
                else
                {
                    this.Swap(index - 1, 2 * index);
                    index = 2 * index + 1;
                }
            }
        }

        private void Swap(int i, int j)
        {
            var tmp = m_List[i];
            m_List[i] = m_List[j];
            m_List[j] = tmp;

            m_Indexes[m_List[i]] = i;
            m_Indexes[m_List[j]] = j;
        }
    }

    public class DisjointSetUnion<T>
    {
        public DisjointSetUnion()
        {
            m_Parent = new Dictionary<T, T>();
            m_Rank = new Dictionary<T, int>();
        }

        public DisjointSetUnion(DisjointSetUnion<T> set)
        {
            m_Parent = new Dictionary<T, T>(set.m_Parent);
            m_Rank = new Dictionary<T, int>(set.m_Rank);
        }

        private readonly Dictionary<T, T> m_Parent;

        private readonly Dictionary<T, int> m_Rank;

        public int GetRank(T x)
        {
            return m_Rank[x];
        }

        public void MakeSet(T x)
        {
            m_Parent[x] = x;
            this.m_Rank[x] = 0;
        }

        public void UnionSets(T x, T y)
        {
            x = this.FindSet(x);
            y = this.FindSet(y);
            if (!x.Equals(y))
            {
                if (m_Rank[x] < m_Rank[y])
                {
                    T t = x;
                    x = y;
                    y = t;
                }
                m_Parent[y] = x;
                if (m_Rank[x] == m_Rank[y])
                {
                    m_Rank[x]++;
                }
            }
        }

        public T FindSet(T x)
        {
            if (x.Equals(m_Parent[x]))
            {
                return x;
            }
            return m_Parent[x] = this.FindSet(m_Parent[x]);
        }
    }

    internal class HamiltonianPathFinder
    {
        public static void Run()
        {
            int n, m;
            Reader.Read(out n, out m);
            List<int>[] a = new List<int>[n];
            for (int i = 0; i < n; i++)
            {
                a[i] = new List<int>();
            }
            for (int i = 0; i < m; i++)
            {
                int x, y;
                Reader.Read(out x, out y);
                a[x].Add(y);
                a[y].Add(x);
            }

            var rnd = new Random();

            bool[] v = new bool[n];
            int[] p = new int[n];
            for (int i = 0; i < n; i++)
            {
                p[i] = -1;
            }
            int first = rnd.Next(n);
            int cur = first;
            v[cur] = true;

            int count = 1;

            while (true)
            {
                var unb = a[cur].Where(u => !v[u]).ToList();
                int d = unb.Count;
                if (d > 0)
                {
                    int next = unb[rnd.Next(d)];
                    v[next] = true;
                    p[cur] = next;
                    cur = next;
                    count++;
                }
                else
                {
                    if (count == n && a[cur].Contains(first))
                    {
                        p[cur] = first;
                        break;
                    }

                    d = a[cur].Count;
                    int pivot;
                    do
                    {
                        pivot = a[cur][rnd.Next(d)];
                    }
                    while (p[pivot] == cur);

                    int next = p[pivot];

                    int x = next;
                    int y = -1;
                    while (true)
                    {
                        int tmp = p[x];
                        p[x] = y;
                        y = x;
                        x = tmp;
                        if (y == cur)
                        {
                            break;
                        }
                    }
                    p[pivot] = cur;
                    cur = next;
                }
            }

            cur = first;
            do
            {
                Console.Write("{0} ", cur);
                cur = p[cur];
            }
            while (cur != first);
        }

        public static void WriteTest(int n)
        {
            Console.WriteLine("{0} {1}", 2 * n, 2 * (n - 1) + n);
            for (int i = 0; i < n - 1; i++)
            {
                Console.WriteLine("{0} {1}", 2 * i, 2 * i + 2);
                Console.WriteLine("{0} {1}", 2 * i + 1, 2 * i + 3);
                //Console.WriteLine("{0} {1}", 2 * i + 1, 2 * i + 2);
                //Console.WriteLine("{0} {1}", 2 * i, 2 * i + 3);
            }
            for (int i = 0; i < n; i++)
            {
                Console.WriteLine("{0} {1}", 2 * i, 2 * i + 1);
            }
        }
    }

    internal class Backtrack<T>
        where T : class
    {
        public Backtrack(Func<T, IEnumerable<T>> generator)
        {
            this.m_Generator = generator;
        }

        public Dictionary<T, T> Generate(T startState)
        {
            var result = new Dictionary<T, T>();
            result.Add(startState, null);

            var queue = new Queue<T>();
            queue.Enqueue(startState);

            while (queue.Count > 0)
            {
                var current = queue.Dequeue();
                var next = m_Generator(current);
                foreach (var state in next)
                {
                    if (!result.ContainsKey(state))
                    {
                        result[state] = current;
                        queue.Enqueue(state);
                    }
                }
            }

            return result;
        }

        private Func<T, IEnumerable<T>> m_Generator;
    }

    public static class Utility
    {
        public static readonly int[] sx = new[] { 1, 0, -1, 0 };

        public static readonly int[] sy = new[] { 0, 1, 0, -1 };

        public static PointInt[] GenerateNeighbors(long x, long y)
        {
            var result = new PointInt[4];
            for (int i = 0; i < 4; i++)
            {
                result[i] = new PointInt(x + sx[i], y + sy[i]);
            }
            return result;
        }

        public static PointInt[] GenerateNeighbors(this PointInt p)
        {
            return GenerateNeighbors(p.X, p.Y);
        }

        public static List<PointInt> GenerateNeighborsWithBounds(long x, long y, int n, int m)
        {
            var result = new List<PointInt>(4);
            for (int i = 0; i < 4; i++)
            {
                var nx = x + sx[i];
                var ny = y + sy[i];
                if (0 <= nx && nx < n && 0 <= ny && ny < m)
                {
                    result.Add(new PointInt(nx, ny));
                }
            }
            return result;
        }

        public static List<PointInt> GenerateNeighborsWithBounds(this PointInt p, int n, int m)
        {
            return GenerateNeighborsWithBounds(p.X, p.Y, n, m);
        }

        public static void Swap<T>(ref T x, ref T y)
        {
            T tmp = x;
            x = y;
            y = tmp;
        }
    }

    public static class FFTMultiply
    {
        public static int[] Multiply(int[] a, int[] b)
        {
            var result = Multiply(
                a.Select(x => new Complex(x, 0)).ToArray(), b.Select(x => new Complex(x, 0)).ToArray());
            return result.Select(x => (int)Math.Round(x.Real)).ToArray();
        }

        public static Complex[] Multiply(Complex[] a, Complex[] b)
        {
            var n = 1;
            while (n < Math.Max(a.Length, b.Length))
            {
                n <<= 1;
            }
            n <<= 1;

            var fa = new Complex[n];
            Array.Copy(a, fa, a.Length);
            var fb = new Complex[n];
            Array.Copy(b, fb, b.Length);

            FFT(fa, false);
            FFT(fb, false);

            for (int i = 0; i < n; i++)
            {
                fa[i] *= fb[i];
            }

            FFT(fa, true);
            for (int i = 0; i < n; i++)
            {
                fa[i] /= n;
            }
            return fa;
        }

        private static void FFT(IList<Complex> a, bool invert)
        {
            var n = a.Count;
            if (n == 1)
            {
                return;
            }

            var a0 = new Complex[n / 2];
            var a1 = new Complex[n / 2];
            for (int i = 0; i < n / 2; i++)
            {
                a0[i] = a[2 * i];
                a1[i] = a[2 * i + 1];
            }
            FFT(a0, invert);
            FFT(a1, invert);

            Complex w = 1;
            var ang = 2 * Math.PI / n * (invert ? -1 : 1);
            Complex wn = new Complex(Math.Cos(ang), Math.Sin(ang));

            for (int i = 0; i < n / 2; i++)
            {
                a[i] = a0[i] + w * a1[i];
                a[i + n / 2] = a0[i] - w * a1[i];
                w *= wn;
            }
        }
    }

    internal class Program
    {
        private static StreamReader m_InputStream;

        private static StreamWriter m_OutStream;

        private static void OpenFiles()
        {
            m_InputStream = new StreamReader("input.txt"); //File.OpenText("input.txt");
            Console.SetIn(m_InputStream);

            m_OutStream = new StreamWriter("output.txt"); //File.CreateText("output.txt");
            Console.SetOut(m_OutStream);
        }

        private static void CloseFiles()
        {
            m_OutStream.Flush();

            m_InputStream.Dispose();
            m_OutStream.Dispose();
        }

        private static void Main()
        {
            //Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;

           // OpenFiles();

            var mainThread = new Thread(() => new Solution().Solve(), 50 * 1024 * 1024);
            mainThread.Start();
            mainThread.Join();

         //   CloseFiles();
        }
    }

    internal class Solution
    {
        public void Solve()
        {
            long mod = 1000000000 + 9;

            long n, m, k;
            Reader.Read(out n, out m, out k);

            var d = n - k * (n - m);
            if (d <= 0)
            {
                Console.WriteLine(m);
                return;
            }

            var ans = ((k - 1) * (n - m)) % mod;
            var t = d / k;
            var matr = new MatrixInt(new long[,] { { 1, 0 }, { 2, 2 } }, mod);
            var mp = Algebra.MatrixBinPower(matr, t);
            ans = (ans + mp[1, 0] * k + d % k) % mod;
            Console.WriteLine(ans);
        }
    }
}