Theatre Square in the capital city of Berland has a rectangular shape with the size *n* × *m* meters. On the occasion of the city's anniversary, a decision was taken to pave the Square with square granite flagstones. Each flagstone is of the size *a* × *a*.

What is the least number of flagstones needed to pave the Square? It's allowed to cover the surface larger than the Theatre Square, but the Square has to be covered. It's not allowed to break the flagstones. The sides of flagstones should be parallel to the sides of the Square.
The input contains three positive integer numbers in the first line: *n*,  *m* and *a* (1 ≤  *n*, *m*, *a* ≤ 10<sup class="upper-index">9</sup>).
6 6 4
4
1 1 1
1
2 1 1
2
1 2 1
2
2 2 1
4
2 1 2
1
1 1 3
1
2 3 4
1
1000000000 1000000000 1
1000000000000000000
12 13 4
12
222 332 5
3015
1000 1000 10
10000
1001 1000 10
10100
100 10001 1000000000
1
1000000000 1000000000 1000000000
1
1000000000 1000000000 999999999
4
1000000000 1000000000 192
27126743055556
1000000000 987654321 1
987654321000000000
456784567 1000000000 51
175618850864484
39916800 134217728 40320
3295710
# m-a-v-e-r-i-c-k
import os, sys, math, heapq, itertools, bisect
from string import ascii_lowercase, ascii_uppercase
from collections import deque,defaultdict, OrderedDict, Counter
#sys.setrecursionlimit(10000)
input = lambda: sys.stdin.readline().rstrip()
ii  = lambda : int(input())                           
si  = lambda : input()                               
mi  = lambda : map(int,input().strip().split(" "))   
msi = lambda : map(str,input().strip().split(" "))   
li  = lambda : list(mi())                            
lsi = lambda : list(msi())
# custom typecasting
orderLowercase = lambda character : ord(character)-97
orderUppercase = lambda character : ord(character)-65
a2n = {chr(k):v for k,v in zip(range(97,97+27),range(1,27))}
n2a = {v:chr(k) for k,v in zip(range(97,97+27),range(1,27))}
toBinary = lambda num : int(str(bin(num))[2:])
iseven = lambda num : num%2==0                       
isodd = lambda num : num%2==1                        
isint = lambda num : isinstance(num, int)
isfloat = lambda num : isinstance(num, float)
isPowerOfTwo = lambda num : num and (not(num & (num - 1)))
positive_infinity = float('inf')
negative_infinity = float('-inf')
startFrom = lambda list_name, target : list(itertools.dropwhile(lambda x : x != target, list_name))
finishBefore = lambda list_name, target : list(itertools.takewhile(lambda x : x != target, list_name))
def swap(array:list,a,b) -> None: array[b],array[a] = array[a],array[b]
def debug(appendMode : str, *var) -> None:
    import t_o_p_g_u_n
    with open(t_o_p_g_u_n.debug_file,appendMode) as f:
        for idx,v in enumerate(var): f.write(f"Query {idx+1}\t>-> {str(v)}\n")
def binary_search_function(input_list:list, low_value:int, high_value:int,  target_value:int) -> None:
    if high_value >= low_value:
        middle = (high_value + low_value) // 2
        if input_list[middle] < target_value: return binary_search_function(input_list, middle +1, high_value, target_value)
        elif input_list[middle] > target_value: return binary_search_function(input_list, low_value, middle-1, target_value)
        else: return middle
    else: return [high_value,low_value]
def bubble_sort(arr:list) -> list:
    i = 0
    while i < len(arr):
        j = i + 1    
        while j < len(arr):
            if arr[j] < arr[i]: temp = arr[i]; arr[i] = arr[j]; arr[j] = temp
            j+=1
        i+=1
    return arr
def currencyChange(change:int)->list:
    currency,n,ans,i = [1, 2, 5, 10, 20, 50, 100, 500, 1000],len(currency),[],n-1
    while i >= 0:
        while (change >= currency[i]): change -= currency[i]; ans.append(currency[i])
        i -= 1
    return ans
# listname, toBreakWhile, startingIndex, forward/reverse
def cycle(list_name : list, breakpoint, startIndex : int = 0, direction : int = 1) -> (int, list) :
    temp,tempStore = 0,[]
    for idx,i in enumerate(itertools.cycle(list_name[::direction])):
        if idx >= startIndex:
            if i!=breakpoint: temp+=1; tempStore.append(i)
            else: break
    return temp, tempStore
def factors(n:int) -> list:
    q = []
    for i in range(1,int(n ** 0.5) + 1):
        if n % i == 0: q.append(i); q.append(n // i)
    return list(sorted(list(set(q))))
def isPrime( n : int ) -> bool:
    if n <= 1: return False
    if n % 2 == 0: return n == 2
    max_div = math.floor(math.sqrt(n))
    for i in range(3, 1 + max_div, 2):
        if n % i == 0: return False
    return True
def isSubsequence(needle:str, haystack:str) -> bool:
    current_pos = 0
    for c in needle:
        current_pos = haystack.find(c, current_pos) + 1
        if current_pos == 0: return False
    return True
def jobSchedulingNoProfit(arr:list)->list:
    n,result,maxHeap = len(arr),[],[]
    arr.sort(key=lambda x: x[1])
    for i in range(n - 1, -1, -1):
        if i == 0: slots_available = arr[i][1]
        else: slots_available = arr[i][1] - arr[i - 1][1]
        heapq.heappush(maxHeap, (-arr[i][2], arr[i][1], arr[i][0]))
        while slots_available and maxHeap:
            profit, deadline, job_id = heapq.heappop(maxHeap)
            slots_available -= 1
            result.append([job_id, deadline])
    result.sort(key=lambda x: x[1])
    return result
    # print result's first element as the jobs name
def jobSchedulingWithProfit(startTime:list, endTime:list, profit:list)->int:
    jobs = sorted(zip(startTime, endTime, profit), key=lambda v: v[1])
    dp = [[0, 0]]
    for s, e, p in jobs:
        i = bisect.bisect(dp, [s + 1]) - 1
        if dp[i][1] + p > dp[-1][1]: dp.append([e, dp[i][1] + p])
    return dp[-1][1]
def LCMofArray(a:list) -> int:
    lcm = a[0]
    for i in range(1,len(a)): lcm = lcm*a[i]//math.gcd(lcm, a[i])
    return lcm
def longestPalindrome(s:list) -> list:
    dp = [[False for i in range(len(s))] for i in range(len(s))]
    for i in range(len(s)): dp[i][i] = True
    max_length = 1
    start = 0
    for l in range(2,len(s)+1):
        for i in range(len(s)-l+1):
            end = i+l
            if l==2:
               if s[i] == s[end-1]:
                  dp[i][end-1]=True
                  max_length = l
                  start = i
            else:
               if s[i] == s[end-1] and dp[i+1][end-2]:
                  dp[i][end-1]=True
                  max_length = l
                  start = i
    return s[start:start+max_length]
def makeTwoBinaryEqual(list1: list, list2: list) -> None:
    absolute,list1Length,list2Length = abs(len(list1) - len(list2)),len(list1),len(list2)
    if list1Length > list2Length :
        for i in range(absolute) : list2.insert(0,'0')
    elif list1Length < list2Length :
        for i in range(absolute) : list1.insert(0,'0')
def maxIncreasingSubArray(arr : list) -> int:
    c,temp = 1,[]
    if len(arr)==1: return 1
    else:
        start,idx = arr[0],1
        while idx < len(arr):
            if arr[idx] > start: start = arr[idx]; c+=1
            else: temp.append(c); start = arr[idx]; c = 1
            idx+=1
        temp.append(c)
        return max(temp)
def maxSubarraySum(n:int, array:list) -> int:
    best = s = 0
    for k in range(n):
        s = max(array[k],s+array[k])
        if s < 0 and max(best,s)==0 and min(best,s)<0: best = s
        else : best = max(best,s)
    return best
def findMinDiff(arr:list, n:int) -> int:
    arr,diff = sorted(arr),10**20
    for i in range(n-1):
        if arr[i+1] - arr[i] < diff: diff = arr[i+1] - arr[i]
    return diff
def findMin(arr:list) -> int:
    n,summation = len(arr),0
    for i in range(0, n): summation = summation + arr[i]
    arr.sort()
    minimum = arr[0]
    maximim = 0
    for i in range(n - 1, 0, -1):
        num = arr[i]
        total = num + minimum
        for j in range(2, num + 1):
            if(num % j == 0):
                d = j
                now = (num // d) + (minimum * d)
                reduce = total - now
                if(reduce > maximim): maximim = reduce
    return summation - maximim
def ncr(n:int,r:int) -> int:
    if r > n: return(0)
    else: return(math.factorial(n) // (math.factorial(n - r) * math.factorial(r)))
def npr(n:int,r:int) -> int:
    if r > n: return(0)
    else: return(math.factorial(n) // math.factorial(n - r))
def pascals_triangle(n:int)-> list:
    triangle = []
    for i in range(n):
        sr = []
        for j in range(i+1): sr.append(math.factorial(i)//(math.factorial(j)*math.factorial(i-j)))
        triangle.append(sr)
    return triangle
def power_two(x:int) -> int: return (x and (not(x & (x - 1))))
def powerset(some_list:list)->list:
    if len(some_list) == 0: return [[]]
    subsets = []
    first_element = some_list[0]
    remaining_list = some_list[1:]
    for partial_subset in powerset(remaining_list):
        subsets.append(partial_subset)
        subsets.append(partial_subset[:] + [first_element])
    return subsets
def prefixSum(arr:list) -> list:
    newArray,idx = [],0
    while idx < len(arr):
        if idx==0: newArray.append(arr[idx])
        else: ans = arr[idx] + newArray[-1]; newArray.append(ans)
        idx+=1
    return newArray
def prime_factors(n:int) -> list:
    q = []
    while n % 2 == 0: q.append(2); n = n // 2
    for i in range(3,int(n ** 0.5) + 1,2):
        while n % i == 0: q.append(i); n = n // i
    if n > 2: q.append(n)
    return list(sorted(q))
def repeatedSubstringPattern(s: str) -> bool:
    for i in range(1,int(len(s)/2)+1):
        if set(s.split(s[0:i])) == {''}: return True 
    return False
def eraseOverlapIntervals(intervals:list) -> int:
    end, cnt = float('-inf'), 0
    for s, e in sorted(intervals, key=lambda x: x[1]):
        if s >= end: end = e
        else: cnt += 1
    return cnt
def seive(n : int) -> list:
    allprime,prime,p = [1],[True for i in range(n + 1)],2
    while (p * p <= n): 
        if (prime[p] == True): 
            for i in range(p ** 2,n + 1,p): prime[i] = False
        p = p + 1
    for p in range(2,n + 1): 
        if prime[p]: allprime.append(p)
    return allprime

def isConsecutive(l:list) -> bool:
    flag = False
    temp = l[0]
    t = l[1:]
    for i in t:
        if i != temp + 1: flag = True; break
        elif i == temp + 1: temp = i
    return flag

def _maverick_() -> None:
    n,m,a = mi()
    ans = math.ceil(m/a) * math.ceil(n/a)
    print(f"{ans}",end="\n")




    

if __name__ == "__main__":
    try: from t_o_p_g_u_n import m_a_v_e_r_i_c_k, _generator_; m_a_v_e_r_i_c_k(); _maverick_(); _generator_(); 
    except (FileNotFoundError,ModuleNotFoundError): _maverick_()


