How to find a maximal odd decomposition of integer M?

前端 未结 3 1277
遥遥无期
遥遥无期 2021-02-09 18:40

Let M be an integer in range [1; 1,000,000,000].

A decomposition of M is a set of unique integers whose sum is equal to M.

A decomposition is odd

3条回答
  •  执念已碎
    2021-02-09 19:32

    I don't see why people have to make it so complicated. An odd decomposition is like a self-conjugate partition turned on its side and unfolded out, for example, n = 13

    4 4 3 2     =>              =>            =>              7 5 1
    
    x x x x   rotate             x         unfold out      x x x x x x x
    x x x x   clockwise     ↖  x  x  ↗      each side       x x x x x
    x x x     45 degrees      x  x  x           =>               x
    x x                      x  x  x  x 
                              x  x  x
    

    The larger an odd decomposition is, the larger the "bounding-square" of the corresponding self-conjugate. By "bounding-square" I mean the top left corner square, which is a constant in all similar-sized odd decompositions. For example, we could have written 13 as the self-conjugate {5,3,3,1,1} and the 9-cell "bounding square" would remain the same, with corresponding odd decomposition {9,3,1}:

    5 3 3 1 1        =>            9 3 1
    
    x x x x x                x x x x x x x x x
    x x x                          x x x
    x x x                            x
    x
    x
    

    To get the odd decomposition with the largest cardinality, find the largest "bounding square" with even remainder.

    Example:

    M = 24
    
    Bounding square | remainder
    1                 23 
    4                 20
    9                 15
    16                8
    25...too large
    
    Place the remainder in any diagonally-symmetric way you like. The simplest way might be
    
    xxxx         xxxxxxxx
    xxxx   =>    xxxx
    xxxx         xxxx
    xxxx         xxxx
                 x
                 x
                 x
                 x
    
    Decompose: 15,5,3,1
    

    I think this Haskell code outputs all possibilities:

    f m = g [1,3..bestRoot*2 - 1] remainder 0 []
      where root = floor (sqrt (fromIntegral m))
            bestRoot = head $ dropWhile (\x -> odd (m - x^2)) [root,root - 1..1]
            remainder = m - bestRoot^2
            g (x:xs) r prev res
              | null xs   = [reverse ((x + r):res)]
              | otherwise = do r' <- takeWhile (<= div remainder bestRoot) [prev,prev + 2..]
                               g xs (r - r') r' ((x + r'):res)
    

    Output:

    *Main> f 24
    [[1,3,5,15],[1,3,7,13],[1,5,7,11],[3,5,7,9]]
    
    *Main> f 23
    [[1,3,19],[1,5,17],[1,7,15],[3,5,15],[3,7,13],[5,7,11]]
    
    *Main> f 38
    [[1,3,5,7,9,13]]
    
    *Main> f 37
    [[1,3,5,7,21],[1,3,5,9,19],[1,3,7,9,17],[1,5,7,9,15],[3,5,7,9,13]]
    
    *Main> f 100
    [[1,3,5,7,9,11,13,15,17,19]]
    

提交回复
热议问题