Stone Division, Revisited

Sort by

recency

|

63 Discussions

|

  • + 0 comments

    code for java7:

    import java.io.*;
    import java.util.*;
    
    class Result {
    
        // Memoization table
        private static Map<Long, Long> memo = new HashMap<>();
    
        // Method to perform stone division
        public static long stoneDivision(long n, List<Long> s) {
            // If the number of stones is 1 or no valid divisor exists, no further splits are possible
            if (n == 1) {
                return 0;
            }
    
            // If we've already computed the result for this number of stones, return it
            if (memo.containsKey(n)) {
                return memo.get(n);
            }
    
            long maxMoves = 0;
            boolean validSplit = false;
    
            // Try to split the pile using each number in S
            for (long x : s) {
                if (n % x == 0 && n != x) {  // Ensure we only divide when n > x to prevent infinite recursion
                    validSplit = true;
                    long numOfPiles = n / x;
                    // One move for splitting and then recursively process the smaller piles
                    long moves = numOfPiles * stoneDivision(x, s) + 1;
                    maxMoves = Math.max(maxMoves, moves);
                }
            }
    
            // If no valid splits are possible, return 0 moves
            if (!validSplit) {
                memo.put(n, 0L);
                return 0L;
            }
    
            // Store the result in memoization table and return
            memo.put(n, maxMoves);
            return maxMoves;
        }
    
        // Method to clear memoization table
        public static void clearMemo() {
            memo.clear();
        }
    }
    
    public class Solution {
        public static void main(String[] args) throws IOException {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out));
    
            int q = Integer.parseInt(bufferedReader.readLine().trim());
    
            for (int qItr = 0; qItr < q; qItr++) {
                String[] firstMultipleInput = bufferedReader.readLine().replaceAll("\\s+$", "").split(" ");
    
                long n = Long.parseLong(firstMultipleInput[0]);
    
                int m = Integer.parseInt(firstMultipleInput[1]);
    
                String[] sTemp = bufferedReader.readLine().replaceAll("\\s+$", "").split(" ");
    
                List<Long> s = new ArrayList<>();
    
                for (int i = 0; i < m; i++) {
                    long sItem = Long.parseLong(sTemp[i]);
                    s.add(sItem);
                }
    
                // Clear memoization table before processing a new query
                Result.clearMemo();
    
                long result = Result.stoneDivision(n, s);
    
                bufferedWriter.write(String.valueOf(result));
                bufferedWriter.newLine();
            }
    
            bufferedReader.close();
            bufferedWriter.close();
        }
    }
    
  • + 1 comment

    My C program prints correct result in test run (see below for Test Case 1), But after I submit it, it failed the Test Case 1. What did I do wrong?

    Your Output (stdout)
        29
    Debug output
        29
        0
        1
        31
    
  • + 1 comment

    I have been testing using the C-code base. I inserted the following simple code:

    long stoneDivision (long n, int s_count, long* s) {
        printf ("30\n");
        return (30);
    }
    

    I compiled it on my RedHat 8.7 system. When I run it with the test input, it cored (tmp.c is the C-code base + above 4 lines of code):

    # gcc tmp.c
    # a.out
    4                       <-- input one line at a time
    64 5             
    2 4 8 16 64
    30               
    Segmentation fault (core dumped)
    

    Looks like there is some issue with the original C-code base.

  • + 0 comments

    C++

    typedef long long llong;
    llong stoneDivision(llong n, vector<llong> const& s, size_t i = 0)
    {
        static unordered_map<llong, llong>* memo;
        if (!memo) {
            auto s1 = s;
            sort(s1.begin(), s1.end(), greater<llong>());
            memo = new unordered_map<llong, llong>();
            llong d = stoneDivision(n, s1);
            delete memo; memo = NULL;
            return d;
        }
        llong d = 0, key = (n << 10) | i;
        auto it = memo->find(key);
        if (it != memo->end()) return it->second;
        for (; i < s.size(); i++)
            if (n > s[i] && n % s[i] == 0)
                d = max(d, 1 + n / s[i] * stoneDivision(s[i], s, i));
        return ((*memo)[key] = d);
    }
    
  • + 0 comments

    This problem permits a really short recursive solution.
    Generally I prefer non-recursive approaches, as recursion tends to be slow (even with memo) and recursion depth limits may apply. However recursive solutions give more concise and elegant code.

    Python3:

    from functools import cache
    def stoneDivision(n, s):
        @cache
        def val(x):
            divs = [i for i in s if x%i == 0 and i!=x]
            return max(1 + val(i) * x//i for i in divs) if divs else 0
        return val(n)